1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Cleanups, fixes and PC/SC support

This commit is contained in:
Werner Koch 2003-08-05 17:11:04 +00:00
parent 9ca4830a5b
commit 1bcf8ef9de
24 changed files with 601 additions and 520 deletions

View file

@ -1,3 +1,23 @@
2003-08-05 Werner Koch <wk@gnupg.org>
* Makefile.am (install-data-local): Dropped check for the ancient
gpgm tool.
(bin_PROGRAMS): Renamed gpg to gpg2 and gpgv to gpgv2. This is so
that it won't conflict with the current stable version of gpg.
* pkglue.c (pk_check_secret_key): New.
* seckey-cert.c (do_check): Reenable this test here again.
* g10.c (main): Add command -K as an alias for
--list-secret-keys. Command "-k" is now an alias to --list-keys.
Remove special treatment of -kv and -kvv.
(set_cmd): Ditto.
(main): Strip a "-cvs" suffix when testing for a version specific
config file.
* status.h, status.c, g10.c [USE_SHM_COPROCESSING]: Removed. This
is not any longer available.
2003-07-29 Werner Koch <wk@gnupg.org>
* g10.c (main): Add secmem features and set the random seed file.

View file

@ -31,8 +31,7 @@ AM_CFLAGS = -DGNUPG_LIBEXECDIR="\"$(libexecdir)\""
endif
needed_libs = ../common/libcommon.a ../jnlib/libjnlib.a
#noinst_PROGRAMS = gpgd
bin_PROGRAMS = gpg gpgv
bin_PROGRAMS = gpg2 gpgv2
common_source = \
global.h gpg.h \
@ -65,7 +64,7 @@ common_source = \
keylist.c \
pkglue.c pkglue.h
gpg_SOURCES = g10.c \
gpg2_SOURCES = g10.c \
$(common_source) \
pkclist.c \
skclist.c \
@ -99,7 +98,7 @@ gpg_SOURCES = g10.c \
card-util.c \
exec.c exec.h
gpgv_SOURCES = gpgv.c \
gpgv2_SOURCES = gpgv.c \
$(common_source) \
verify.c
@ -111,8 +110,8 @@ gpgv_SOURCES = gpgv.c \
# $(common_source)
LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@
gpg_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error
gpgv_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error
gpg2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error
gpgv2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error
$(PROGRAMS): $(needed_libs)
@ -120,8 +119,4 @@ install-data-local:
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
$(INSTALL_DATA) $(srcdir)/options.skel \
$(DESTDIR)$(pkgdatadir)/options.skel
@set -e;\
if test -f $(DESTDIR)$(bindir)/gpgm ; then \
echo "removing obsolete gpgm binary" ; \
rm $(DESTDIR)$(bindir)/gpgm ; \
fi

107
g10/g10.c
View file

@ -61,7 +61,8 @@ enum cmd_and_opt_values { aNull = 0,
aEncr = 'e',
aEncrFiles,
oInteractive = 'i',
oKOption = 'k',
aListKeys = 'k',
aListSecretKeys = 'K',
oDryRun = 'n',
oOutput = 'o',
oQuiet = 'q',
@ -93,15 +94,11 @@ enum cmd_and_opt_values { aNull = 0,
aDeleteKeys,
aDeleteSecretKeys,
aDeleteSecretAndPublicKeys,
aKMode,
aKModeC,
aImport,
aFastImport,
aVerify,
aVerifyFiles,
aListKeys,
aListSigs,
aListSecretKeys,
aSendKeys,
aRecvKeys,
aSearchKeys,
@ -213,7 +210,6 @@ enum cmd_and_opt_values { aNull = 0,
oTrustModel,
oForceOwnertrust,
oEmuChecksumBug,
oRunAsShmCP,
oSetFilename,
oForYourEyesOnly,
oNoForYourEyesOnly,
@ -514,7 +510,6 @@ static ARGPARSE_OPTS opts[] = {
/* Not yet used */
/* { aListTrustPath, "list-trust-path",0, "@"}, */
{ aPipeMode, "pipemode", 0, "@" },
{ oKOption, NULL, 0, "@"},
{ oPasswdFD, "passphrase-fd",1, "@" },
#ifdef __riscos__
{ oPasswdFile, "passphrase-file",2, "@" },
@ -549,7 +544,6 @@ static ARGPARSE_OPTS opts[] = {
{ oTrustModel, "trust-model", 2, "@"},
{ oForceOwnertrust, "force-ownertrust", 2, "@"},
{ oEmuChecksumBug, "emulate-checksum-bug", 0, "@"},
{ oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
{ oSetFilename, "set-filename", 2, "@" },
{ oForYourEyesOnly, "for-your-eyes-only", 0, "@" },
{ oNoForYourEyesOnly, "no-for-your-eyes-only", 0, "@" },
@ -879,8 +873,6 @@ set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
cmd = aSignSym;
else if( cmd == aSym && new_cmd == aSign )
cmd = aSignSym;
else if( cmd == aKMode && new_cmd == aSym )
cmd = aKModeC;
else if( ( cmd == aSign && new_cmd == aClearsign )
|| ( cmd == aClearsign && new_cmd == aSign ) )
cmd = aClearsign;
@ -1167,9 +1159,6 @@ main( int argc, char **argv )
int pwfd = -1;
int with_fpr = 0; /* make an option out of --fingerprint */
int any_explicit_recipient = 0;
#ifdef USE_SHM_COPROCESSING
ulong requested_shm_size=0;
#endif
#ifdef __riscos__
riscos_global_defaults();
@ -1276,19 +1265,6 @@ main( int argc, char **argv )
opt.strict=0;
log_set_strict(0);
}
#ifdef USE_SHM_COPROCESSING
else if( pargs.r_opt == oRunAsShmCP ) {
/* does not make sense in a options file, we do it here,
* so that we are the able to drop setuid as soon as possible */
opt.shm_coprocess = 1;
requested_shm_size = pargs.r.ret_ulong;
}
else if ( pargs.r_opt == oStatusFD ) {
/* this is needed to ensure that the status-fd filedescriptor is
* initialized when init_shm_coprocessing() is called */
set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) );
}
#endif
}
#ifdef HAVE_DOSISH_SYSTEM
@ -1301,11 +1277,7 @@ main( int argc, char **argv )
set_homedir (buf);
}
#endif
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess ) {
init_shm_coprocessing(requested_shm_size, 1 );
}
#endif
/* Initialize the secure memory. */
gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
maybe_setuid = 0;
@ -1318,9 +1290,14 @@ main( int argc, char **argv )
if( default_config )
{
/* Try for a version specific config file first */
/* Try for a version specific config file first but strip our
usual cvs suffix. That suffix indicates that it is not yet
the given version but we already want this config file. */
configname = make_filename(opt.homedir,
"gpg" EXTSEP_S "conf-" SAFE_VERSION, NULL );
if (!strcmp (configname + strlen (configname) - 4, "-cvs"))
configname[strlen (configname)-4] = 0;
if(access(configname,R_OK))
{
xfree (configname);
@ -1458,7 +1435,6 @@ main( int argc, char **argv )
case oInteractive: opt.interactive = 1; break;
case oVerbose: g10_opt_verbose++;
opt.verbose++; opt.list_sigs=1; break;
case oKOption: set_cmd( &cmd, aKMode ); break;
case oBatch: opt.batch = 1; nogreeting = 1; break;
case oUseAgent:
@ -1631,17 +1607,6 @@ main( int argc, char **argv )
case oGnuPG: opt.compliance = CO_GNUPG; break;
case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break;
case oCompressSigs: opt.compress_sigs = 1; break;
case oRunAsShmCP:
#ifndef __riscos__
# ifndef USE_SHM_COPROCESSING
/* not possible in the option file,
* but we print the warning here anyway */
log_error("shared memory coprocessing is not available\n");
# endif
#else /* __riscos__ */
riscos_not_implemented("run-as-shm-coprocess");
#endif /* __riscos__ */
break;
case oSetFilename: opt.set_filename = pargs.r.ret_str; break;
case oForYourEyesOnly: eyes_only = 1; break;
case oNoForYourEyesOnly: eyes_only = 0; break;
@ -2276,21 +2241,6 @@ main( int argc, char **argv )
set_cmd( &cmd, aListKeys);
}
if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */
if( cmd == aKModeC ) {
opt.fingerprint = 1;
cmd = aKMode;
}
opt.list_sigs = 0;
if( opt.verbose > 2 )
opt.check_sigs++;
if( opt.verbose > 1 )
opt.list_sigs++;
opt.verbose = opt.verbose > 1;
g10_opt_verbose = opt.verbose;
}
/* Compression algorithm 0 means no compression at all */
if( opt.def_compress_algo == 0)
opt.compress = 0;
@ -2302,12 +2252,11 @@ main( int argc, char **argv )
if( opt.verbose > 1 )
set_packet_list_mode(1);
/* Add the keyrings, but not for some special commands and not in
case of "-kvv userid keyring". Also avoid adding the secret
keyring for a couple of commands to avoid unneeded access in
case the secrings are stored on a floppy */
if( cmd != aDeArmor && cmd != aEnArmor
&& !(cmd == aKMode && argc == 2 ) )
/* Add the keyrings, but not for some special commands. Also
avoid adding the secret keyring for a couple of commands to
avoid unneeded access in case the secrings are stored on a
floppy */
if( cmd != aDeArmor && cmd != aEnArmor )
{
if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys
&& cmd != aVerify && cmd != aVerifyFiles
@ -2544,34 +2493,6 @@ main( int argc, char **argv )
free_strlist(sl);
break;
case aKMode: /* list keyring -- NOTE: This will be removed soon */
if( argc < 2 ) { /* -kv [userid] */
sl = NULL;
if (argc && **argv)
add_to_strlist2( &sl, *argv, utf8_strings );
public_key_list( sl );
free_strlist(sl);
}
else if( argc == 2 ) { /* -kv userid keyring */
if( access( argv[1], R_OK ) ) {
log_error(_("can't open %s: %s\n"),
print_fname_stdin(argv[1]), strerror(errno));
}
else {
/* add keyring (default keyrings are not registered in this
* special case */
keydb_add_resource( argv[1], 0, 0 );
sl = NULL;
if (**argv)
add_to_strlist2( &sl, *argv, utf8_strings );
public_key_list( sl );
free_strlist(sl);
}
}
else
wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") );
break;
case aKeygen: /* generate a key */
if( opt.batch ) {
if( argc > 1 )

View file

@ -287,8 +287,39 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
}
/* Check whether SKEY is a suitable secret key. */
int
pk_check_secret_key (int algo, gcry_mpi_t *skey)
{
gcry_sexp_t s_skey;
int rc;
if (algo == GCRY_PK_DSA)
{
rc = gcry_sexp_build (&s_skey, NULL,
"(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
skey[0], skey[1], skey[2], skey[3], skey[4]);
}
else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
{
rc = gcry_sexp_build (&s_skey, NULL,
"(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
skey[0], skey[1], skey[2], skey[3]);
}
else if (algo == GCRY_PK_RSA)
{
rc = gcry_sexp_build (&s_skey, NULL,
"(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
skey[0], skey[1], skey[2], skey[3], skey[4],
skey[5]);
}
else
return GPG_ERR_PUBKEY_ALGO;
if (!rc)
{
rc = gcry_pk_testkey (s_skey);
gcry_sexp_release (s_skey);
}
return rc;
}

View file

@ -29,6 +29,7 @@ int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
gcry_mpi_t *pkey);
int pk_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
gcry_mpi_t *skey);
int pk_check_secret_key (int algo, gcry_mpi_t *skey);
#endif /*GNUPG_G10_PKGLUE_H*/

View file

@ -215,14 +215,13 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
return gpg_error (GPG_ERR_BAD_PASSPHRASE);
}
/* the checksum may fail, so we also check the key itself */
#warning fixme - we need to reenable this
/* res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey ); */
/* if( res ) { */
/* copy_secret_key( sk, save_sk ); */
/* passphrase_clear_cache ( keyid, sk->pubkey_algo ); */
/* free_secret_key( save_sk ); */
/* return gpg_error (GPG_ERR_BAD_PASSPHRASE); */
/* } */
res = pk_check_secret_key (sk->pubkey_algo, sk->skey);
if (res) {
copy_secret_key( sk, save_sk );
passphrase_clear_cache ( keyid, sk->pubkey_algo );
free_secret_key( save_sk );
return gpg_error (GPG_ERR_BAD_PASSPHRASE);
}
free_secret_key( save_sk );
sk->is_protected = 0;
}

View file

@ -1,5 +1,6 @@
/* status.c
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -25,21 +26,6 @@
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#ifdef USE_SHM_COPROCESSING
#ifdef USE_CAPABILITIES
#include <sys/capability.h>
#endif
#ifdef HAVE_SYS_IPC_H
#include <sys/types.h>
#include <sys/ipc.h>
#endif
#ifdef HAVE_SYS_SHM_H
#include <sys/shm.h>
#endif
#if defined(HAVE_MLOCK)
#include <sys/mman.h>
#endif
#endif
#include "gpg.h"
#include "util.h"
@ -56,13 +42,6 @@
static FILE *statusfp;
#ifdef USE_SHM_COPROCESSING
static int shm_id = -1;
static volatile char *shm_area;
static size_t shm_size;
static int shm_is_locked;
#endif /*USE_SHM_COPROCESSING*/
static void
progress_cb (void *ctx, const char *what, int printchar, int current, int total)
@ -291,179 +270,6 @@ write_status_buffer ( int no, const char *buffer, size_t len, int wrap )
#ifdef USE_SHM_COPROCESSING
#ifndef IPC_RMID_DEFERRED_RELEASE
static void
remove_shmid( void )
{
if( shm_id != -1 ) {
shmctl ( shm_id, IPC_RMID, 0);
shm_id = -1;
}
}
#endif
void
init_shm_coprocessing ( ulong requested_shm_size, int lock_mem )
{
char buf[100];
struct shmid_ds shmds;
#ifndef IPC_RMID_DEFERRED_RELEASE
atexit( remove_shmid );
#endif
requested_shm_size = (requested_shm_size + 4095) & ~4095;
if ( requested_shm_size > 2 * 4096 )
log_fatal("too much shared memory requested; only 8k are allowed\n");
shm_size = 4096 /* one page for us */ + requested_shm_size;
shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0700 );
if ( shm_id == -1 )
log_fatal("can't get %uk of shared memory: %s\n",
(unsigned)shm_size/1024, strerror(errno));
#if !defined(IPC_HAVE_SHM_LOCK) \
&& defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
/* part of the old code which uses mlock */
shm_area = shmat( shm_id, 0, 0 );
if ( shm_area == (char*)-1 )
log_fatal("can't attach %uk shared memory: %s\n",
(unsigned)shm_size/1024, strerror(errno));
log_debug("mapped %uk shared memory at %p, id=%d\n",
(unsigned)shm_size/1024, shm_area, shm_id );
if( lock_mem ) {
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
#endif
/* (need the cast for Solaris with Sun's workshop compilers) */
if ( mlock ( (char*)shm_area, shm_size) )
log_info("locking shared memory %d failed: %s\n",
shm_id, strerror(errno));
else
shm_is_locked = 1;
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+p") );
#endif
}
#ifdef IPC_RMID_DEFERRED_RELEASE
if( shmctl( shm_id, IPC_RMID, 0) )
log_fatal("shmctl IPC_RMDID of %d failed: %s\n",
shm_id, strerror(errno));
#endif
if( shmctl( shm_id, IPC_STAT, &shmds ) )
log_fatal("shmctl IPC_STAT of %d failed: %s\n",
shm_id, strerror(errno));
if( shmds.shm_perm.uid != getuid() ) {
shmds.shm_perm.uid = getuid();
if( shmctl( shm_id, IPC_SET, &shmds ) )
log_fatal("shmctl IPC_SET of %d failed: %s\n",
shm_id, strerror(errno));
}
#else /* this is the new code which handles the changes in the SHM
* semantics introduced with Linux 2.4. The changes is that we
* now change the permissions and then attach to the memory.
*/
if( lock_mem ) {
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
#endif
#ifdef IPC_HAVE_SHM_LOCK
if ( shmctl (shm_id, SHM_LOCK, 0) )
log_info("locking shared memory %d failed: %s\n",
shm_id, strerror(errno));
else
shm_is_locked = 1;
#else
log_info("Locking shared memory %d failed: No way to do it\n", shm_id );
#endif
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+p") );
#endif
}
if( shmctl( shm_id, IPC_STAT, &shmds ) )
log_fatal("shmctl IPC_STAT of %d failed: %s\n",
shm_id, strerror(errno));
if( shmds.shm_perm.uid != getuid() ) {
shmds.shm_perm.uid = getuid();
if( shmctl( shm_id, IPC_SET, &shmds ) )
log_fatal("shmctl IPC_SET of %d failed: %s\n",
shm_id, strerror(errno));
}
shm_area = shmat( shm_id, 0, 0 );
if ( shm_area == (char*)-1 )
log_fatal("can't attach %uk shared memory: %s\n",
(unsigned)shm_size/1024, strerror(errno));
log_debug("mapped %uk shared memory at %p, id=%d\n",
(unsigned)shm_size/1024, shm_area, shm_id );
#ifdef IPC_RMID_DEFERRED_RELEASE
if( shmctl( shm_id, IPC_RMID, 0) )
log_fatal("shmctl IPC_RMDID of %d failed: %s\n",
shm_id, strerror(errno));
#endif
#endif
/* write info; Protocol version, id, size, locked size */
sprintf( buf, "pv=1 pid=%d shmid=%d sz=%u lz=%u", (int)getpid(),
shm_id, (unsigned)shm_size, shm_is_locked? (unsigned)shm_size:0 );
write_status_text( STATUS_SHM_INFO, buf );
}
/****************
* Request a string from client
* If bool, returns static string on true (do not free) or NULL for false
*/
static char *
do_shm_get( const char *keyword, int hidden, int bool )
{
size_t n;
byte *p;
char *string;
if( !shm_area )
BUG();
shm_area[0] = 0; /* msb of length of control block */
shm_area[1] = 32; /* and lsb */
shm_area[2] = 1; /* indicate that we are waiting on a reply */
shm_area[3] = 0; /* clear data available flag */
write_status_text( bool? STATUS_SHM_GET_BOOL :
hidden? STATUS_SHM_GET_HIDDEN : STATUS_SHM_GET, keyword );
do {
pause_on_sigusr(1);
if( shm_area[0] || shm_area[1] != 32 || shm_area[2] != 1 )
log_fatal("client modified shm control block - abort\n");
} while( !shm_area[3] );
shm_area[2] = 0; /* reset request flag */
p = (byte*)shm_area+32;
n = p[0] << 8 | p[1];
p += 2;
if( n+32+2+1 > 4095 )
log_fatal("client returns too large data (%u bytes)\n", (unsigned)n );
if( bool )
return p[0]? "" : NULL;
string = hidden? xmalloc_secure ( n+1 ) : xmalloc ( n+1 );
memcpy(string, p, n );
string[n] = 0; /* make sure it is a string */
if( hidden ) /* invalidate the memory */
memset( p, 0, n );
return string;
}
#endif /* USE_SHM_COPROCESSING */
static int
myread(int fd, void *buf, size_t count)
{
@ -541,10 +347,6 @@ cpr_enabled()
{
if( opt.command_fd != -1 )
return 1;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return 1;
#endif
return 0;
}
@ -555,10 +357,6 @@ cpr_get_no_help( const char *keyword, const char *prompt )
if( opt.command_fd != -1 )
return do_get_from_fd ( keyword, 0, 0 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 0, 0 );
#endif
for(;;) {
p = tty_get( prompt );
return p;
@ -572,10 +370,6 @@ cpr_get( const char *keyword, const char *prompt )
if( opt.command_fd != -1 )
return do_get_from_fd ( keyword, 0, 0 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 0, 0 );
#endif
for(;;) {
p = tty_get( prompt );
if( *p=='?' && !p[1] && !(keyword && !*keyword)) {
@ -608,10 +402,6 @@ cpr_get_hidden( const char *keyword, const char *prompt )
if( opt.command_fd != -1 )
return do_get_from_fd ( keyword, 1, 0 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 1, 0 );
#endif
for(;;) {
p = tty_get_hidden( prompt );
if( *p == '?' && !p[1] ) {
@ -628,10 +418,6 @@ cpr_kill_prompt(void)
{
if( opt.command_fd != -1 )
return;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return;
#endif
tty_kill_prompt();
return;
}
@ -644,10 +430,6 @@ cpr_get_answer_is_yes( const char *keyword, const char *prompt )
if( opt.command_fd != -1 )
return !!do_get_from_fd ( keyword, 0, 1 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return !!do_shm_get( keyword, 0, 1 );
#endif
for(;;) {
p = tty_get( prompt );
trim_spaces(p); /* it is okay to do this here */
@ -672,10 +454,6 @@ cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt )
if( opt.command_fd != -1 )
return !!do_get_from_fd ( keyword, 0, 1 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return !!do_shm_get( keyword, 0, 1 );
#endif
for(;;) {
p = tty_get( prompt );
trim_spaces(p); /* it is okay to do this here */

View file

@ -110,10 +110,6 @@ void write_status_buffer ( int no,
void write_status_text_and_buffer ( int no, const char *text,
const char *buffer, size_t len, int wrap );
#ifdef USE_SHM_COPROCESSING
void init_shm_coprocessing ( ulong requested_shm_size, int lock_mem );
#endif /*USE_SHM_COPROCESSING*/
int cpr_enabled(void);
char *cpr_get( const char *keyword, const char *prompt );
char *cpr_get_no_help( const char *keyword, const char *prompt );