print.c revision d29b2c4438482eb00488be49a1f5d6835f455546
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <alloca.h>
#include "sgs.h"
#include "rtc.h"
#include "conv.h"
#include "_crle.h"
#include "msg.h"
/*
* Display the command line required to regenerate the configuration file.
*
* Under normal mode the command is printed on one line to make it more
* available for grep(1) use. Under verbose mode the command is separated
* into each argument (a little more readable perhaps when the arguments are
* numerous of have long pathnames).
*
* Note that for version 1 configuration files we never used to generate any
* command-line information, and as the attempt to do so is only a best effort
* don't bother printing anything.
*/
static void
{
char *cmd;
int output = 0;
} else {
return;
}
if (output++ == 0) {
else
} else {
else
}
}
}
/*
* Establish the argument required to generate the associated object.
*/
static const char *
{
if (flags & RTC_OBJ_ALTER) {
if (flags & RTC_OBJ_DUMP) {
if (flags & RTC_OBJ_GROUP)
return (MSG_ORIG(MSG_CMD_DUMPGRP));
else
return (MSG_ORIG(MSG_CMD_DUMPIND));
} else {
if (flags & RTC_OBJ_OPTINAL)
return (MSG_ORIG(MSG_CMD_OPTIONAL));
else
return (MSG_ORIG(MSG_CMD_ALTER));
}
} else {
if (flags & RTC_OBJ_GROUP)
return (MSG_ORIG(MSG_CMD_GRP));
else
return (MSG_ORIG(MSG_CMD_IND));
}
}
/*
* Fabricate a system default search path. If an update is requested, and
* new search paths are specified while no configuration file exists, or if a
* configuration file does exist but doesn't specify this particular search
* path, create any system defaults. The intent is to allow
* system default, rather than have the user have to determine and specify
* this default themselves.
*/
static int
{
const char *path;
char **list;
switch (flag) {
case CRLE_EDLIB:
#if M_CLASS == ELFCLASS64
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#else
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#endif
break;
case CRLE_ESLIB:
#if M_CLASS == ELFCLASS64
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#else
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#endif
break;
case CRLE_ADLIB:
break;
case CRLE_ASLIB:
break;
default:
return (1);
}
}
/*
* Establish the flags required to generate the associated object. Actually
* the flags are already part of the object being inspected from the present
* configuration file, but instead of using them all, which can cause some
* unsuspected propagation down the inspect() family, only use those flags that
* would have been contributed from crle()'s calls to inspect.
*/
static Half
{
flags &=
return (flags | RTC_OBJ_CMDLINE);
}
/*
* Dump a configuration files information. This routine is very close to the
* scanconfig() in libcrle.
*/
/*ARGSUSED2*/
static INSCFG_RET
{
const char *strtbl;
/*
* If there is an Rtc_id present, the Rtc_head follows it.
* Otherwise, it is at the top.
*/
if (RTC_ID_TEST(addr)) {
} else {
/*
* When updating an existing config file that is lacking
* the Rtc_id block, don't put one into the resulting file.
*/
}
/*
* The rest of the configuration file can only be examined by
* a program of the same ELFCLASS, byte order, and hardware
* architecture as the one that created it.
*/
#ifdef _ELF64
/* 64-bit program with an existing 32-bit file? Abort. */
return (INSCFG_RET_FAIL);
}
#else
/* 32-bit program with an existing 64-bit file? Restart. */
return (INSCFG_RET_NEED64);
/*
* 32-bit program with an existing 32-bit file, but the
* user specified the -64 option? Abort
*/
if (c_class != ELFCLASS32) {
return (INSCFG_RET_FAIL);
}
#endif
/*
* Now that the ELFCLASS has been settled, ensure that the
* byte order and hardware match. Unlike ELFCLASS, where restarting
* the other version is an option, we cannot work around a mismatch
* of these attributes.
*/
if (id) { /* Rtc_id is present */
/*
* Was the file produced by compatible hardware?
* ELFCLASS doesn't matter here, because we can
* adjust for that, but byte order and machine type do.
*/
&inv_buf1),
&inv_buf2),
&inv_buf3),
&inv_buf4));
return (INSCFG_RET_FAIL);
}
}
/* LINTED */
/*
* If the configuration file has a version higher than we
* recognise, we face two issues:
* (1) Updates are not possible because we have no
* way to recognise or propagate the new features.
* This has to be a fatal error.
* (2) Printing has the risk that we may have been
* handed something other than a real config file, as
* well as the fact that we can't display the information
* for the new features. So, we print a warning, but
* continue on to do the best we can with it.
*/
return (INSCFG_RET_FAIL);
} else {
}
}
/*
* If this is a version 1 configuration file we can't generate accurate
* update information, or the command-line used to create the file.
*/
}
/*
* Construct the original command line argument.
*/
return (INSCFG_RET_FAIL);
}
/*
* Start analyzing the configuration files header information.
*/
const char *fmt;
if (head->ch_dlflags)
else
/*
* If the file has an id block, show the information
*/
if (id)
&inv_buf1),
&inv_buf2),
&inv_buf3));
/*
* Construct the original command line argument.
*/
return (INSCFG_RET_FAIL);
/*
* Construct any -f usage.
*/
if (head->ch_dlflags &&
&dl_flag_buf));
return (INSCFG_RET_FAIL);
}
} else {
/*
* Establish any -f usage.
*/
if (head->ch_dlflags &&
}
/*
* Determine if this configuration file is only applicable to a specific
* application.
*/
char *alter;
/*
* Determine the output directory for the files
* alternative name.
*/
*alter = '\0';
RTC_OBJ_GROUP | RTC_OBJ_CMDLINE)) != 0)
return (INSCFG_RET_FAIL);
} else {
/*
* Construct the original command line arguments.
*/
return (INSCFG_RET_FAIL);
return (INSCFG_RET_FAIL);
}
}
/*
* Analyze any alternative library path and trusted directory entries.
*/
if (head->ch_edlibpath) {
const char *str;
#ifndef SGS_PRE_UNIFIED_PROCESS
else
}
#endif
return (INSCFG_RET_FAIL);
} else {
return (INSCFG_RET_FAIL);
}
} else {
/*
* If we've been asked to update a configuration
* file, and no existing default ELF search
* path exists, but the user is going to add new
* entries, fabricate the system defaults so
* that the users get added to them.
*/
return (INSCFG_RET_FAIL);
}
} else {
/*
* Indicate any system default.
*/
#if M_CLASS == ELFCLASS64
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#else
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#endif
}
}
if (head->ch_eslibpath) {
const char *str;
#ifndef SGS_PRE_UNIFIED_PROCESS
else
}
#endif
return (INSCFG_RET_FAIL);
} else {
return (INSCFG_RET_FAIL);
}
} else {
/*
* If we've been asked to update a configuration
* file, and no existing default ELF secure
* path exists, but the user is going to add new
* entries, fabricate the system defaults so
* that the users get added to them.
*/
return (INSCFG_RET_FAIL);
}
} else {
/*
* Indicate any system default.
*/
#if M_CLASS == ELFCLASS64
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#else
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#endif
}
}
if (head->ch_adlibpath) {
const char *str;
return (INSCFG_RET_FAIL);
} else {
return (INSCFG_RET_FAIL);
}
} else {
/*
* If we've been asked to update a configuration
* file, and no existing default AOUT search
* path exists, but the user is going to add new
* entries, fabricate the system defaults so
* that the users get added to them.
*/
return (INSCFG_RET_FAIL);
}
/*
* Indicate any system default.
*/
}
}
if (head->ch_aslibpath) {
const char *str;
return (INSCFG_RET_FAIL);
} else {
return (INSCFG_RET_FAIL);
}
} else {
/*
* If we've been asked to update a configuration
* file, and no existing default AOUT secure
* path exists, but the user is going to add new
* entries, fabricate the system defaults so
* that the users get added to them.
*/
return (INSCFG_RET_FAIL);
}
/*
* Indicate any system default.
*/
}
}
/*
* Display any environment variables.
*/
const char *str;
return (INSCFG_RET_FAIL);
} else {
} else {
}
return (INSCFG_RET_FAIL);
}
}
}
/*
*/
/* LINTED */
/* LINTED */
/*
* Print the filter and filtee string pair.
*/
/*
* Print each filtee.
*/
/* LINTED */
_fltetbl++) {
}
fltrtbl++;
}
}
}
/*
* Display any memory reservations required for any alternative
* objects.
*/
/*
* If there's no hash table there's nothing else to process.
*/
return (INSCFG_RET_OK);
}
/*
* Traverse the directory and filename arrays.
*/
const char *str;
/*
* Simplify recreation by using any command-line directories.
* If we're dealing with a version 1 configuration file use
* every directory.
*/
return (INSCFG_RET_FAIL);
(RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) ==
continue;
} else {
/* LINTED */
return (INSCFG_RET_FAIL);
}
}
/*
* If this isn't an update print the directory name. If the
* directory has no entries (possible if the directory is a
* symlink to another directory, in which case we record the
* real path also), don't bother printing it unless we're in
* verbose mode.
*/
(RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) ==
continue;
}
/*
* Under verbose mode validate any real directory entry - the
* same test will be carried out by ld.so.1.
*/
}
}
/*
* Only update individual files that were originally
* specified on the command-line. Or, if this is a
* version 1 configuration file use every file that
* isn't part of an all-entries directory.
*/
if (((flags & RTC_OBJ_CMDLINE) &&
/*
* Determine whether this file requires an
* alternative, and if so, and we haven't
* already an alternative in affect, create one.
*/
*alter = '\0';
if ((objdir == 0) ||
} else
alter = 0;
}
return (INSCFG_RET_FAIL);
continue;
}
if (alter) {
_cmd);
return (INSCFG_RET_FAIL);
}
/* LINTED */
return (INSCFG_RET_FAIL);
}
continue;
/*
* Although we record both full pathnames and their
* simple filenames (basename), only print the simple
* names unless we're under verbose mode.
*/
else
str);
}
/*
* Under verbose mode validate any real file entry - the
* same test will be carried out by ld.so.1.
*/
str);
}
}
}
}
return (INSCFG_RET_OK);
/*
* If we've in verbose mode scan the hash list.
*/
/* LINTED */
hash += 2;
/*
* Scan the hash buckets looking for valid entries.
*/
const char *str;
if (*hash == 0)
continue;
/*
* Determine whether there are other objects chained to this
* bucket.
*/
&config_obj_buf));
}
}
return (INSCFG_RET_OK);
}
{
int fd;
/*
* Open the configuration file, determine its size and map it in.
*/
#ifndef _ELF64
/* Must restart if user requested a 64-bit file */
if (c_class == ELFCLASS64)
return (INSCFG_RET_NEED64);
#endif
/*
* To allow an update (-u) from scratch, fabricate any
* default search and secure paths that the user
* intends to add to.
*/
return (INSCFG_RET_FAIL);
}
return (INSCFG_RET_FAIL);
}
return (INSCFG_RET_FAIL);
}
return (INSCFG_RET_FAIL);
}
return (INSCFG_RET_OK);
/*
* Otherwise if the user is inspecting a default
* configuration file that doesn't exist inform
* them and display the ELF defaults.
*/
} else {
#if M_CLASS == ELFCLASS64
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#else
#ifndef SGS_PRE_UNIFIED_PROCESS
#else
#endif
#endif
}
return (INSCFG_RET_OK);
}
}
/*
* Otherwise there's an error condition in accessing the file.
*/
return (INSCFG_RET_FAIL);
}
return (INSCFG_RET_FAIL);
}
return (INSCFG_RET_FAIL);
}
/*
* Print the contents of the configuration file.
*/
return (error);
}