static char rcsid[] = "@(#)$Id: shared.c,v 1.67 2006/06/29 17:26:41 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.67 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************/
/*
* This file is compiled only if dlopen() is available, so
* that file does not need to be guarded with #ifdef
*/
#include "headers.h"
DEBUG_VAR(Debug,__FILE__,"dl");
#include "shared_imp.h"
#include "connection_imp.h"
#include "rc_imp.h"
#include "save_opts.h"
#include "s_me.h"
#include "cs_imp.h"
#include "ss_imp.h"
#include "s_elm.h"
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
#if ANSI_C
#define S_(x) static x;
#else
#define S_(x)
#endif
struct shared_FT * shared_folder_types = NULL;
int shared_folder_type_count = 0;
/* FIXME -- is shared_SE_option_types really needed */
struct shared_SEOT * shared_SE_option_types = NULL;
int shared_SE_option_type_count = 0;
struct shared_CST * shared_CS_types = NULL;
int shared_CS_type_count = 0;
struct shared_MCF * shared_MCF_types = NULL;
int shared_MCF_type_count = 0;
int use_sharedfunc P_((char **value, int enter,
int lineno, char *filename));
struct ImpInfo **library_list = NULL;
int library_list_count = 0;
static char * give_shname P_((const char *tag));
static char * give_shname(tag)
CONST char *tag;
{
char * ret = elm_message(FRM("%s/%s%s%s"),
SHARED_DIR,
SHARED_LIBPREFIX,
tag,
SHARED_LIBSUFFIX);
DPRINT(Debug,4,(&Debug,"use-*-library %s => %s\n",tag,ret));
return ret;
}
S_(RC_post_init_f no_rc_post_init)
static void no_rc_post_init(errors)
int *errors;
{
/* Nothing */
}
static wants_rand_bits_f no_wants_rand_bits;
static void no_wants_rand_bits (buf,size,entropy_bits)
CONST char *buf;
int size;
int entropy_bits;
{
/* Nothing */
}
struct ImpInfo * give_impinfo(tag)
CONST char * tag;
{
int i;
for (i = 0; i < library_list_count; i++) {
if (0 == strcmp(library_list[i]->tag,tag))
return library_list[i];
}
library_list = safe_realloc(library_list,
(i+1) * sizeof(library_list[0]));
library_list[i] = safe_malloc(sizeof (* library_list[i]) );
bzero((void *)library_list[i], sizeof (* library_list[i]));
library_list[i]->valid = 0;
library_list[i]->tag = safe_strdup(tag);
library_list[i]->shname = give_shname(tag);
library_list[i]->handle = NULL;
library_list[i]->base_lists_updated = 0;
library_list[i]->regs = NULL;
library_list[i]->regs_count = 0;
library_list[i]->rc_options = NULL;
library_list[i]->rc_option_count = 0;
library_list[i]->rc_post_init = no_rc_post_init;
library_list[i]->wants_rand_bits = no_wants_rand_bits;
library_list_count = i+1;
return library_list[i];
}
int give_rnum(I,var)
struct ImpInfo * I;
struct dt_shared_info *var;
{
int i;
int k;
for (i = 0; i < I->regs_count; i++)
if (I->regs[i].var == var)
return i;
DPRINT(Debug,7,(&Debug,
"give_rnum: Adding var %p to %s => rnum=%d\n",
var,I->shname,i));
I->regs = safe_realloc(I->regs,
(I->regs_count+1) * sizeof (I->regs[0]));
I->regs[i].var = var;
I->regs[i].valid = 0;
I->regs[i].updated = 0;
I->regs[i].r.dummy = NULL;
DPRINT(Debug,10,(&Debug,
"give_rnum: [%p]->regs[%d].valid=%d\n",
I,i,I->regs[i].valid));
if (SHARED_LOADER_magic != var->loader->magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"give_rnum",
"Bad magic bumber",0);
var->loader->func_zero(var,& (I->regs[i]) );
I->regs_count = i+1;
for (k = 0; k < var->shared_list_len; k++)
if (var->shared_list[k] == I)
goto found;
DPRINT(Debug,7,(&Debug,
"give_rnum: Adding %s to var %p shared_list (index %d)\n",
I->shname,var,k));
var->shared_list = safe_realloc(var->shared_list,
(k+1) * sizeof (var->shared_list[0]));
var->shared_list[k] = I;
var->shared_list_len = k+1;
found:
DPRINT(Debug,7,(&Debug,
"give_rnum=%d [var %p]\n",i,var));
return i;
}
void load_code0(I)
struct ImpInfo *I;
{
if (! I->handle) {
DPRINT(Debug,4,(&Debug," ... library loading %s\n",
I->shname));
I->handle = dlopen(I->shname,RTLD_NOW);
if (! I->handle) {
lib_error(CATGETS(elm_msg_cat, MeSet,
MeDLopen0Error,
"library %s: %s: %s"),
I->tag, I->shname,
dlerror());
I->valid = 0;
return;
}
}
if (! I->base_lists_updated) {
/* union hack to avoid warnings about casting
* between pointer-to-object and pointer-to-function
*/
union F8 {
void * ptr;
provides_RC_options_f * f8;
} f8;
union F9 {
void * ptr;
RC_post_init_f * f9;
} f9;
union F10 {
void * ptr;
wants_rand_bits_f * f10;
} f10;
/* F11 reserved */
f8.ptr = dlsym( I->handle, "provides_RC_options");
f9.ptr = dlsym( I->handle, "RC_post_init");
f10.ptr = dlsym( I->handle, "wants_rand_bits");
if (!f8.f8) {
DPRINT(Debug,7,(&Debug, " ... NO provides_RC_options\n"));
}
if (!f9.f9) {
DPRINT(Debug,7,(&Debug, " ... NO RC_post_init\n"));
}
if (!f10.f10) {
DPRINT(Debug,7,(&Debug, " ... NO wants_rand_bits\n"));
}
if (f8.f8) {
int count;
size_t s_res8;
struct rc_save_info_rec * res8 = f8.f8(&count, &s_res8);
if (s_res8 != sizeof (*res8)) {
DPRINT(Debug,1,(&Debug,"... struct rc_save_info_rec mismatch: %d should be %d\n",
s_res8,sizeof (*res8)));
} else {
DPRINT(Debug,7,(&Debug," ... provides_RC_options: count %d\n",
count));
I->rc_options = res8;
I->rc_option_count = count;
}
}
if (f9.f9) {
I->rc_post_init = f9.f9;
DPRINT(Debug,7,(&Debug," ... RC_post_init\n"));
}
if (f10.f10) {
I->wants_rand_bits = f10.f10;
DPRINT(Debug,7,(&Debug," ... wants_rand_bits\n"));
}
I->base_lists_updated = 1;
}
/* TODO: Other bookkeeping */
}
int reg_code1(I,r)
struct ImpInfo *I;
int r;
{
int res;
if (SHARED_LOADER_magic != I->regs[r].var->loader->magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"reg_code1",
"Bad magic bumber",0);
res = I->regs[r].valid;
if ( I->regs[r].valid &&
! I->regs[r].updated ) {
DPRINT(Debug,7,(&Debug,"reg_code1: Checking library %s ... [%d var %p]\n",
I->shname,r,I->regs[r].var));
res = I->regs[r].var->loader->func_reg(I, r);
I->regs[r].updated = 1;
DPRINT(Debug,7,(&Debug,"reg_code1: ... %s result = %d [%d var %p] valid = %d\n",
I->shname,res,r,I->regs[r].var,
I->regs[r].valid));
} else {
DPRINT(Debug,7,(&Debug,
"reg_code1: Skipping library %s ... [%d var %p] valid=%d updated=%d\n",
I->shname,r,I->regs[r].var,
I->regs[r].valid,
I->regs[r].updated));
}
return res;
}
static void load_code P_((int idx));
static void load_code(idx)
int idx;
{
DPRINT(Debug,4,(&Debug,"library [%d] - processing %s ... \n",
idx, library_list[idx]->shname));
load_code0(library_list[idx]);
}
static void unreg1 P_((struct ImpInfo * I, int r));
static void unreg1(I,r)
struct ImpInfo * I;
int r;
{
if (SHARED_LOADER_magic != I->regs[r].var->loader->magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"unreg1",
"Bad magic bumber",0);
I->regs[r].var->loader->
func_unreg(I, r);
I->regs[r].valid = 0;
I->regs[r].updated = 0;
DPRINT(Debug,10,(&Debug,
"unreg1: [%p]->regs[%d].valid=%d\n",
I,r,I->regs[r].valid));
}
static void unload_code P_((int idx));
static void unload_code(idx)
int idx;
{
if (library_list[idx]->regs_count > 0) {
int i;
for (i = 0; i < library_list[idx]->regs_count; i++) {
if (library_list[idx]->regs[i].valid &&
library_list[idx]->regs[i].updated) {
unreg1(library_list[idx],i);
}
}
}
/* TODO: Other bookkeeping */
if (library_list[idx]->handle) {
DPRINT(Debug,4,(&Debug,"library [%d] - unloading %s\n",
idx,library_list[idx]->shname));
dlclose(library_list[idx]->handle);
library_list[idx]->handle = NULL;
}
}
int tag_ok(name)
CONST char *name;
{
if ('\0' == *name)
return 0;
if (strspn(name,"abcdefghijklmnopqrstuvwxyz") < 3)
return 0;
return strlen(name) ==
strspn(name,
"abcdefghijklmnopqrstuvwxyz0123456789-");
}
static int libraries_loaded = 0;
static int locate_and_load_library P_((const char *prefix));
static int locate_and_load_library(prefix)
CONST char *prefix;
{
int i;
for (i = 0; i < library_list_count; i++) {
if (0 == strcmp(library_list[i]->tag,prefix)) {
/* Do not update libraries_loaded
because this loads only one library
*/
if (library_list[i]->valid &&
!libraries_loaded)
load_code(i);
if (library_list[i]->valid) {
int r;
for (r = 0; r < library_list[i]->regs_count; r++)
reg_code1(library_list[i],r);
}
return i;
}
}
return -1;
}
void load_shared_libs()
{
int i;
if (libraries_loaded)
return;
for (i = 0; i < library_list_count; i++) {
if (library_list[i]->valid)
load_code(i);
/* NOTE: This do not load variable specific
code ...
*/
}
libraries_loaded = 1;
}
void load_shared_libs1(var)
struct dt_shared_info *var;
{
int i;
if (var->libraries_loaded)
return;
DPRINT(Debug,7,(&Debug,"Loading [var %p] ...\n",var));
for (i = 0; i < var->shared_list_len; i++) {
if (var->shared_list[i]->valid)
load_code0(var->shared_list[i]);
if (var->shared_list[i]->valid) {
int r = give_rnum(var->shared_list[i],var);
DPRINT(Debug,7,(&Debug,
"Prosessing [var %p] %d, %s : valid=%d => r=%d\n",
var, i,
var->shared_list[i]->shname,
var->shared_list[i]->valid,
r));
reg_code1(var->shared_list[i],r);
} else {
DPRINT(Debug,7,(&Debug,
"Skipping [var %p] %d, %s : valid=%d\n",
var, i,
var->shared_list[i]->shname,
var->shared_list[i]->valid));
}
}
DPRINT(Debug,7,(&Debug,"Loading [var %p] done.\n",var));
var->libraries_loaded = 1;
}
void register_hidden_library(parent,lib)
struct dt_shared_info *parent;
struct dt_shared_info *lib;
{
if (lib->hidden_var)
panic("SHARED PANIC",__FILE__,__LINE__,
"process_lib_reg",
"register_hidden_library have children or already registered",0);
lib->hidden_var = parent->hidden_var;
parent->hidden_var = lib;
}
static int process_lib_reg P_((struct rc_save_info_rec *r,
char *value, int lineno,
char *filename));
static int process_lib_reg(r,value,lineno,filename)
struct rc_save_info_rec *r;
char *value;
int lineno;
char *filename;
{
int ret = 1;
struct dt_shared_info *S = r->val.shared;
char * temp = safe_strdup(value);
char *p;
if (S->loader->magic != SHARED_LOADER_magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"process_lib_reg",
"Bad magic bumber (1)",0);
for (p = strtok(temp," "); p; p = strtok(NULL," ")) {
if (!tag_ok(p)) {
lib_error(CATGETS(elm_msg_cat, MeSet,
MeInvalidUseXLib,
"%s: %s: Invalid name"),
r->name,p);
ret = 0;
} else {
struct ImpInfo * I = give_impinfo(p);
int rnum = give_rnum(I,S);
/* We do not load code here with dlopen, because we
cant load code only when it is needed.
*/
if (0 == access(I->shname,ACCESS_EXISTS)) {
struct dt_shared_info *S1;
I->valid = 1;
libraries_loaded = 0; /* Rescan... */
I->regs[rnum].valid = 1;
S->libraries_loaded = 0;
DPRINT(Debug,10,(&Debug,
"process_lib_reg: [%p]->regs[%d].valid=%d\n",
I,rnum,I->regs[rnum].valid));
for (S1 = S->hidden_var; S1; S1 = S1->hidden_var) {
int rnum = give_rnum(I,S1);
I->regs[rnum].valid = 1;
S->libraries_loaded = 0;
DPRINT(Debug,10,(&Debug,
"process_lib_reg: [%p]->regs[%d].valid=%d (hidden)\n",
I,rnum,I->regs[rnum].valid));
}
} else {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet,
MeNonExistUseXLib,
"%s: %s: %s: %s"),
r->name,I->tag,I->shname,
error_description(err));
ret = 0;
}
}
}
free(temp);
return ret;
}
S_(rc_parse_line dt_SHARED_parse_line)
static int dt_SHARED_parse_line(r,lcl,value,lineno,filename, negate)
struct rc_save_info_rec *r;
int lcl;
char *value;
int lineno;
char *filename;
int negate;
{
int i;
if (negate) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadNegate,
"!%s is not supported in line %d in \"%s\" file"),
r->name,lineno,filename);
return 0;
}
if (r->val.shared->loader->magic != SHARED_LOADER_magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"dt_SHARED_parse_line",
"Bad magic bumber (1)",0);
for (i = 0; i < r->val.shared->shared_list_len; i++) {
int j;
for (j = 0; j < r->val.shared->shared_list[i]->regs_count; j++) {
if (r->val.shared->shared_list[i]->regs[j].var->loader->magic !=
SHARED_LOADER_magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"dt_SHARED_parse_line",
"Bad magic bumber (2)",0);
if (r->val.shared == r->val.shared->shared_list[i]->regs[j].var) {
r->val.shared->shared_list[i]->regs[j].valid = 0;
DPRINT(Debug,10,(&Debug,
"dt_SHARED_parse_line: [%p]->regs[%d].valid=%d\n",
r->val.shared->shared_list[i],
j,
r->val.shared->shared_list[i]->regs[j].valid));
goto found1;
}
}
panic("SHARED PANIC",__FILE__,__LINE__,
"dt_SHARED_parse_line",
"No info on list",0);
found1:;
}
return process_lib_reg(r,value,lineno,filename);
}
S_(rc_parse_cline dt_SHARED_parse_cline)
static int dt_SHARED_parse_cline(r,lcl,value,lineno,filename)
struct rc_save_info_rec *r;
int lcl;
char *value;
int lineno;
char *filename;
{
return process_lib_reg(r,value,lineno,filename);
}
S_(rc_print_value dt_SHARED_print_value)
static void dt_SHARED_print_value(F,r,comment)
FILE *F;
struct rc_save_info_rec *r;
int comment;
{
int i;
int len=0;
if (r->val.shared->loader->magic != SHARED_LOADER_magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"dt_SHARED_print_value",
"Bad magic bumber (1)",0);
if (comment)
fprintf(F, "### ");
fprintf(F, "%s =", r->name);
for (i = 0; i < r->val.shared->shared_list_len; i++) {
int j;
for (j = 0; j < r->val.shared->shared_list[i]->regs_count; j++) {
if (r->val.shared->shared_list[i]->regs[j].var->loader->magic !=
SHARED_LOADER_magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"dt_SHARED_print_value",
"Bad magic bumber (2)",0);
if (r->val.shared == r->val.shared->shared_list[i]->regs[j].var) {
goto found1;
}
}
panic("SHARED PANIC",__FILE__,__LINE__,
"dt_SHARED_print_value",
"No info on list",0);
found1:
if (r->val.shared->shared_list[i]->regs[j].valid) {
char * s = r->val.shared->shared_list[i]->tag;
if (strlen(s) + len > 72) {
if (!comment)
fprintf(F, "\n\t");
else
fprintf(F, "\n###\t");
len = 8;
}
else {
fprintf(F, " ");
++len;
}
fprintf(F, "%s", s);
len += strlen(s);
}
}
fprintf(F,"\n");
}
S_(rc_get_value dt_SHARED_get_value)
static char * dt_SHARED_get_value(r)
struct rc_save_info_rec *r;
{
/* static pointer to buffer accross invocations */
static char * return_buffer = NULL;
int i;
int len=0;
return_buffer = strmcpy(return_buffer,""); /* Reset result */
if (r->val.shared->loader->magic != SHARED_LOADER_magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"dt_SHARED_get_value",
"Bad magic bumber (1)",0);
for (i = 0; i < r->val.shared->shared_list_len; i++) {
int j;
for (j = 0; j < r->val.shared->shared_list[i]->regs_count; j++) {
if (r->val.shared->shared_list[i]->regs[j].var->loader->magic !=
SHARED_LOADER_magic)
panic("SHARED PANIC",__FILE__,__LINE__,
"dt_SHARED_get_value",
"Bad magic bumber (2)",0);
if (r->val.shared == r->val.shared->shared_list[i]->regs[j].var) {
goto found1;
}
}
panic("SHARED PANIC",__FILE__,__LINE__,
"dt_SHARED_get_value",
"No info on list",0);
found1:
if (r->val.shared->shared_list[i]->regs[j].valid) {
char * s = r->val.shared->shared_list[i]->tag;
if (return_buffer[0])
return_buffer = strmcat(return_buffer," ");
return_buffer = strmcat(return_buffer,s);
}
}
return return_buffer;
}
struct rc_type rc_DT_SHARED = { RCTYPE_magic,
dt_SHARED_parse_line, dt_SHARED_parse_cline,
dt_SHARED_print_value, dt_SHARED_get_value };
int verify_shared_index(i)
struct ImpInfo *i;
{
if (i->handle &&
i->valid)
return 1;
return 0;
}
struct SE_option_type * get_option_type(prefix)
CONST char *prefix;
{
int i;
int idx1 = locate_and_load_library(prefix);
for (i = 0; i < shared_SE_option_type_count; i++) {
struct ImpInfo *I = shared_SE_option_types[i].imp_idx;
if (library_list[idx1] == I) {
if (! I->handle) {
lib_error(CATGETS(elm_msg_cat, MeSet,
MeInvalidOptionTag,
"Options %s:* ignored -- code not loaded"),
prefix);
return NULL;
}
return shared_SE_option_types[i].T;
}
}
lib_error(CATGETS(elm_msg_cat, MeSet,
MeInvalidOptionTag,
"Options %s:* ignored -- code not loaded"),
prefix);
return NULL;
}
void mark_shared_changed(A)
void *A;
{
int i;
for (i = 0; i < library_list_count; i++) {
int x;
if (!library_list[i]->handle)
continue;
for (x = 0; x < library_list[i]->rc_option_count; x++) {
if (library_list[i]->rc_options[x].val.dummy == A) {
mark_XX(& (library_list[i]->rc_options[x]));
}
}
}
}
void mark_fshared_changed(A)
option_func *A;
{
int i;
for (i = 0; i < library_list_count; i++) {
int x;
if (!library_list[i]->handle)
continue;
for (x = 0; x < library_list[i]->rc_option_count; x++) {
if (library_list[i]->rc_options[x].func_val == A) {
mark_XX(& (library_list[i]->rc_options[x]));
}
}
}
}
int give_options(tag,rc_options,rc_option_count)
char *tag;
struct rc_save_info_rec ** rc_options;
int * rc_option_count;
{
int idx1 = locate_and_load_library(tag);
*rc_options = NULL;
*rc_option_count = 0;
if (idx1 < 0 ||
!library_list[idx1]->handle)
return 0;
*rc_options = library_list[idx1]->rc_options;
*rc_option_count = library_list[idx1]->rc_option_count;
return 1;
}
static void seed_rand_bits1(const char *buf, int size,
int entropy_bits);
static void seed_rand_bits1(buf,size,entropy_bits)
CONST char *buf;
int size;
int entropy_bits;
{
int i;
DPRINT(Debug,10,(&Debug,
"Seeding random generator %d bytes (%d entropy bits)\n",
size,entropy_bits));
if (entropy_bits > size*8)
panic("SHARED PANIC",__FILE__,__LINE__,"seed_rand_bits1",
"Impossible entropy",0);
/* Only seed libraries which are loaded */
for (i = 0; i < library_list_count; i++) {
if (library_list[i]->handle) {
/* We should perhaps mangle data so same bits are
not given to different modules
*/
library_list[i]->wants_rand_bits(buf,size,entropy_bits);
}
}
}
void seed_rand_bits(buf,size,entropy_bits)
CONST char *buf;
int size;
int entropy_bits;
{
static char buffer[1024];
static int byte_count = 0;
static int entropy_count = 0;
DPRINT(Debug,10,(&Debug,
"Got random generator %d bytes (%d entropy bits)\n",
size,entropy_bits));
if (entropy_bits > size*8)
panic("SHARED PANIC",__FILE__,__LINE__,"seed_rand_bits",
"Impossible entropy",0);
if (size > sizeof buffer)
seed_rand_bits1(buf,size,entropy_bits);
else {
int i;
if (size + byte_count > sizeof buffer) {
seed_rand_bits1(buffer,byte_count,entropy_count);
byte_count = 0;
entropy_count = 0;
}
/* We can just XOR bits ... */
for (i = 0; i < size; i++)
buffer[byte_count++] ^= buf[i];
if (byte_count > sizeof buffer)
panic("SHARED PANIC",__FILE__,__LINE__,"seed_rand_bits",
"Overflow",0);
entropy_count += entropy_bits;
if (entropy_count > 16 && library_list_count) {
seed_rand_bits1(buffer,byte_count,entropy_count);
byte_count = 0;
entropy_count = 0;
}
}
}
void post_init_shared_options(errors)
int *errors;
{
int i;
/* Automatically move libraries out from
use-library ...
*/
/* load generic ... */
load_shared_libs1(&use_shared_all);
/* unreg possible registered but no longer valid... */
for (i = 0; i < library_list_count; i++) {
int j;
for (j = 0; j < library_list[i]->regs_count; j++) {
if (! library_list[i]->regs[j].valid &&
library_list[i]->regs[j].updated) {
unreg1(library_list[i],j);
}
}
}
/* Unload possible loaded but no longer valid... */
for (i = 0; i < library_list_count; i++) {
if (!library_list[i]->valid) {
DPRINT(Debug,4,(&Debug,"Unloading no longer valid library %s\n",
library_list[i]->tag));
unload_code(i);
}
}
/* Only post_init libraries which are loaded
(other do not have options)
*/
for (i = 0; i < library_list_count; i++) {
if (library_list[i]->handle &&
library_list[i]->rc_option_count > 0) {
library_list[i]->rc_post_init(errors);
}
}
}
void print_local_shared_options(F,global)
FILE *F;
int global;
{
int i;
/* We want print options of all shared libs */
load_shared_libs();
for (i = 0; i < library_list_count; i++) {
if (library_list[i]->handle &&
library_list[i]->rc_option_count > 0) {
int x;
fprintf(F,"\n");
elm_fprintf(F,
CATGETS(elm_msg_cat, MeSet, MeElmrcSection,
"# Options for %s section (shared library)\n#\n\n"),
library_list[i]->tag);
fprintf(F,"%s:\n",
library_list[i]->tag);
DPRINT(Debug,8,(&Debug, " -- library %s -- %d options\n",
library_list[i]->tag,
library_list[i]->rc_option_count));
for (x = 0; x < library_list[i]->rc_option_count; x++) {
int local_value;
/** skip system-only options **/
if (!global &
(library_list[i]->rc_options[x].flags & FL_SYS) ) {
DPRINT(Debug,8,(&Debug,
"shlib/option %d -- \"%s\" system-only, flags=%0x\n",
x,library_list[i]->rc_options[x].name,
save_info[x].flags ));
continue;
}
if (global &
!(library_list[i]->rc_options[x].flags & FL_SYS) &&
!(library_list[i]->rc_options[x].flags & FL_CHANGED)) {
DPRINT(Debug,8,(&Debug,
"shlib/option %d -- \"%s\" user option, flags=%0x\n",
x,library_list[i]->rc_options[x].name,
save_info[x].flags ));
continue;
}
if (global)
local_value =
library_list[i]->rc_options[x].flags & FL_CHANGED;
else
local_value =
library_list[i]->rc_options[x].flags & FL_LOCAL;
if (RCTYPE_magic != library_list[i]->rc_options[x].dt_type->magic) {
DPRINT(Debug,1,(&Debug,
"shlib/option %d -- \"%s\" BAD, flags=%0x (library=%s)\n",
x,library_list[i]->rc_options[x].name,
save_info[x].flags,
library_list[i]->tag));
panic("RC PANIC",__FILE__,__LINE__,
"print_local_shared_options",
"Bad config item type",0);
}
library_list[i]->
rc_options[x].dt_type->
print_value(F,
& library_list[i]->rc_options[x],
!local_value);
}
}
}
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1