static char rcsid[] = "@(#)$Id: rc_handle.c,v 1.40 2006/06/21 18:30:32 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.40 $ $State: Exp $ * * Author: Kari Hurtta (was hurtta+elm@ozone.FMI.FI) **************************************************************************** * * Some of code comes from ../src/read_rc.c and ../src/save_opts.c. These * are following copyright: * * Copyright (c) 1988-1992 USENET Community Trust * Copyright (c) 1986,1987 Dave Taylor *****************************************************************************/ #include "headers.h" #include "rc_imp.h" #include "save_opts.h" #ifdef USE_DLOPEN #include "shared_imp.h" #endif #include "s_elm.h" DEBUG_VAR(Debug,__FILE__,"config"); #ifdef ANSI_C static rc_parse_line dt_SYN_parse_line; #endif static int dt_SYN_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { if (negate) { char buffer[SLEN]; buffer[0] = '!'; strfcpy(buffer+1, r->val.str, sizeof buffer -1); if ( do_set(lcl,buffer,value,filename)) return 1; } else { if ( do_set(lcl, r->val.str, value, filename)) return 1; } return 0; } #ifdef ANSI_C static rc_parse_cline BAD_parse_cline; #endif static int BAD_parse_cline(r,lcl,value,lineno,filename) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadContinuationInElmrc, "Key \"%s\" does not accept continuation lines in line %d in \"%s\" file"), r->name,lineno,filename); return 0; } #if ANSI_C static rc_print_value NO_print_value; #endif static void NO_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { /* Empty */ } #if ANSI_C static rc_get_value NO_get_value; #endif static char * NO_get_value(r) struct rc_save_info_rec *r; { return "*bad*"; } struct rc_type rc_DT_SYN = { RCTYPE_magic, dt_SYN_parse_line, BAD_parse_cline, NO_print_value, NO_get_value }; #ifdef ANSI_C static rc_parse_line dt_STR_parse_line; #endif static int dt_STR_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { 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 (strlen(value) >= r->size_val) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmLongValueInElmrc, "Value of \"%s\" in line %d in \"%s\" file is too long"), r->name,lineno,filename); return 0; } strfcpy(r->val.str, value, r->size_val); if (r->flags & FL_NOSPC) { char *s; for (s = r->val.str; *s; ++s) if (*s == '_') *s=' '; } return 1; } /* Returns pointer to static area */ #if ANSI_C static rc_get_value dt_STR_get_value; #endif static char * dt_STR_get_value(r) struct rc_save_info_rec *r; { if (r->flags & FL_NOSPC) { static char buffer[SLEN]; char *t, *s; for (t = r->val.str, s = buffer; *t && s - buffer < sizeof buffer -1; ++t, ++s) if ((*s = *t) == ' ') *s='_'; *s = '\0'; return buffer; } else return r->val.str; } #if ANSI_C static rc_print_value dt_STR_print_value; #endif static void dt_STR_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { char * s = dt_STR_get_value(r); if (comment) fprintf(F, "### "); fprintf(F, "%s = %s\n", r->name, s); DPRINT(Debug,9,(&Debug, " option \"%s\", value=\"%s\"\n", r->name,s )); } struct rc_type rc_DT_STR = { RCTYPE_magic, dt_STR_parse_line, BAD_parse_cline, dt_STR_print_value, dt_STR_get_value }; #ifdef ANSI_C static rc_parse_line dt_NUM_parse_line; #endif static int dt_NUM_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { char *p; long l = strtol(value,&p,10); 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; } *(r->val.num) = l; return 1; } #if ANSI_C static rc_print_value dt_NUM_print_value; #endif static void dt_NUM_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { if (comment) fprintf(F, "### "); fprintf(F, "%s = %d\n", r->name, *r->val.num); DPRINT(Debug,9,(&Debug, " option \"%s\", value=%d\n", r->name,*r->val.num )); } /* Returns static pointer */ #if ANSI_C static rc_get_value dt_NUM_get_value; #endif static char * dt_NUM_get_value(r) struct rc_save_info_rec *r; { static char * buffer = NULL; if (buffer) free(buffer); buffer = elm_message(FRM("%d"), *r->val.num); return buffer; } struct rc_type rc_DT_NUM = { RCTYPE_magic, dt_NUM_parse_line, BAD_parse_cline, dt_NUM_print_value, dt_NUM_get_value }; #ifdef ANSI_C static rc_parse_line dt_BOL_parse_line; #endif static int dt_BOL_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { if (negate) { if (r->flags & FL_OR) *(r->val.bol) |= !is_it_on(value); else if (r->flags & FL_AND) *(r->val.bol) &= !is_it_on(value); else *(r->val.bol) = !is_it_on(value); } else { if (r->flags & FL_OR) *(r->val.bol) |= is_it_on(value); else if (r->flags & FL_AND) *(r->val.bol) &= is_it_on(value); else *(r->val.bol) = is_it_on(value); } return 1; } #if ANSI_C static rc_print_value dt_BOL_print_value; #endif static void dt_BOL_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { char * s; if (comment) fprintf(F, "### "); s = *r->val.bol ? "ON" : "OFF"; fprintf(F, "%s = %s\n", r->name, s); DPRINT(Debug,9,(&Debug, " option \"%s\", value=%s\n", r->name,s )); } #if ANSI_C static rc_get_value dt_BOL_get_value; #endif static char * dt_BOL_get_value(r) struct rc_save_info_rec *r; { return *r->val.bol ? "ON" : "OFF"; } struct rc_type rc_DT_BOL = { RCTYPE_magic, dt_BOL_parse_line, BAD_parse_cline, dt_BOL_print_value, dt_BOL_get_value }; #ifdef ANSI_C static rc_parse_line dt_CHR_parse_line; #endif static int dt_CHR_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { 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; } *(r->val.chr) = value[0]; return 1; } #if ANSI_C static rc_print_value dt_CHR_print_value; #endif static void dt_CHR_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { if (comment) fprintf(F, "### "); fprintf(F, "%s = %c\n", r->name, *r->val.chr); DPRINT(Debug,9,(&Debug, " option \"%s\", value=%c\n", r->name, *r->val.chr)); } #if ANSI_C static rc_get_value dt_CHR_get_value; #endif static char * dt_CHR_get_value(r) struct rc_save_info_rec *r; { static char buffer[2]; buffer[0] = *r->val.chr; buffer[1] = '\0'; return buffer; } struct rc_type rc_DT_CHR = { RCTYPE_magic, dt_CHR_parse_line, BAD_parse_cline, dt_CHR_print_value, dt_CHR_get_value }; #ifdef ANSI_C static rc_parse_line dt_SORT_parse_line; #endif static int dt_SORT_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { char buffer[SLEN]; char *s = buffer; int f,y; f = 1; strfcpy(buffer, shift_lower(value), sizeof buffer); if (strncmp(s, "rev-", 4) == 0 || strncmp(s, "reverse-", 8) == 0) { f = -f; s = index(s, '-') + 1; } if (negate) f = -f; for (y= 0; r->val.sort->sortval[y].kw; y++) { if (equal(s, r->val.sort->sortval[y].kw)) break; } if (r->val.sort->sortval[y].kw) { r->val.sort->val = f > 0 ? r->val.sort->sortval[y].sv : - r->val.sort->sortval[y].sv; } else { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadSortKeyInElmrc, "I can't understand sort key \"%s\" in line %d in \"%s\" file"), value, lineno, filename); return 0; } return 1; } static char * give_sort_value P_((struct dt_sort_info *ptr)); static char * give_sort_value(ptr) struct dt_sort_info *ptr; { int y; for (y= 0; ptr->sortval[y].kw; y++) { if (ptr->sortval[y].sv == ptr->val) return ptr->sortval[y].kw; else if (ptr->sortval[y].sv == - ptr->val) { static char * buffer = NULL; buffer = strmcpy(buffer,"reverse-"); buffer = strmcat(buffer, ptr->sortval[y].kw); return buffer; } } return "*bad*"; } #if ANSI_C static rc_get_value dt_SORT_get_value; #endif static char * dt_SORT_get_value(r) struct rc_save_info_rec *r; { return give_sort_value(r->val.sort); } CONST char * give_dt_sort_as_str(ptr) struct dt_sort_info *ptr; { return give_sort_value(ptr); } int give_dt_sort_as_int(ptr) struct dt_sort_info *ptr; { return ptr->val; } void set_dt_sort_as_int(ptr,val) struct dt_sort_info *ptr; int val; { ptr->val = val; } #if ANSI_C static rc_print_value dt_SORT_print_value; #endif static void dt_SORT_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { if (comment) fprintf(F, "### "); fprintf(F, "%s = %s\n", r->name, dt_SORT_get_value(r)); } struct rc_type rc_DT_SORT = { RCTYPE_magic, dt_SORT_parse_line, BAD_parse_cline, dt_SORT_print_value, dt_SORT_get_value }; #ifdef ANSI_C static rc_parse_line dt_MLT_parse_line; #endif static int dt_MLT_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 ok = 1; char **s; 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; } for (s = r->val.mlt; *s; ++s) { if (!do_set(lcl, *s, value, filename)) ok = 0; } return ok; } struct rc_type rc_DT_MLT = { RCTYPE_magic, dt_MLT_parse_line, BAD_parse_cline, NO_print_value, NO_get_value }; #ifdef ANSI_C static rc_parse_line dt_PRM_parse_line; #endif static int dt_PRM_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { char *s = value; int m = 0; char *modecharp = "rwxrwxrwx"; int modebit = 0400; char c; 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; } while ((c = *s++) != '\0') { if (c == *modecharp) m |= modebit; else if (c != '-') { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadModeInElmrc, "I can't understand file permissions \"%s\" in line %d in \"%s\" file"), value, lineno,filename); return 0; } modecharp++; modebit >>= 1; } if (*modecharp != '\0') { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadModeInElmrc, "I can't understand file permissions \"%s\" in line %d in \"%s\" file"), value, lineno,filename); return 0; } *(r->val.num) = m; return 1; } #if ANSI_C static rc_print_value dt_PRM_print_value; #endif static void dt_PRM_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { char *s = mode_to_str(*(r->val.num)); if (comment) fprintf(F, "### "); fprintf(F, "%s = %s\n", r->name, s); } #if ANSI_C static rc_get_value dt_PRM_get_value; #endif static char * dt_PRM_get_value(r) struct rc_save_info_rec *r; { return mode_to_str(*(r->val.num)); } struct rc_type rc_DT_PRM = { RCTYPE_magic, dt_PRM_parse_line, BAD_parse_cline, dt_PRM_print_value, dt_PRM_get_value }; #ifdef ANSI_C static rc_parse_line dt_FUNC_parse_line; #endif static int dt_FUNC_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { 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->func_val(&value,1,lineno,filename)) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadValueInElmrc, "Value of \"%s\" in line %d in \"%s\" file is bad"), r->name,lineno,filename); return 0; } return 1; } #if ANSI_C static rc_print_value dt_FUNC_print_value; #endif static void dt_FUNC_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { char *s = NULL; r->func_val(&s,0,0,NULL); if (s) { if (comment) fprintf(F, "### "); fprintf(F, "%s = %s\n", r->name, s); } } #if ANSI_C static rc_get_value dt_FUNC_get_value; #endif static char * dt_FUNC_get_value(r) struct rc_save_info_rec *r; { char *s = NULL; r->func_val(&s,0,0,NULL); return s; } struct rc_type rc_DT_FUNC = { RCTYPE_magic, dt_FUNC_parse_line, BAD_parse_cline, dt_FUNC_print_value, dt_FUNC_get_value }; #ifdef ANSI_C static rc_parse_line dt_LONG_parse_line; #endif static int dt_LONG_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { char *p; long l; 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; } l = strtol(value,&p,10); *(r->val.l_num) = l; return 1; } #if ANSI_C static rc_print_value dt_LONG_print_value; #endif static void dt_LONG_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { if (comment) fprintf(F, "### "); fprintf(F, "%s = %ld\n", r->name, *r->val.l_num); } #if ANSI_C static rc_get_value dt_LONG_get_value; #endif static char * dt_LONG_get_value(r) struct rc_save_info_rec *r; { static char * buffer = NULL; if (buffer) free(buffer); buffer = elm_message(FRM("%ld"), *r->val.l_num); return buffer; } struct rc_type rc_DT_LONG = { RCTYPE_magic, dt_LONG_parse_line, BAD_parse_cline, dt_LONG_print_value, dt_LONG_get_value }; /* Appends expanded value to list 0 == failure 1 == succeed */ int expand_dt_path(ptr,fieldname,val, recursive) struct dt_path_info *ptr; char *fieldname; char *val; int recursive; /* 0 if not recursive call */ { int ret = 1; int is_file = ptr->flags & PATH_file; int is_dir = ptr->flags & PATH_dir; int is_quote = (ptr->flags & PATH_quote) && 0 == recursive; int is_expand = (ptr->flags & PATH_expand) && 0 == recursive; int is_sep_comma = ptr->flags & PATH_sep_comma; int is_sep_colon = ptr->flags & PATH_sep_colon; int is_sep_space = 0 == recursive; int is_quote_single = (ptr->flags & PATH_quote_single) && 0 == recursive; int convert_underline = (ptr->flags & PATH_convert_underline) && 0 == recursive; char *p; char * start_val = NULL; int q = 0; int quit_flag = 0; if (!recursive) { DPRINT(Debug,8,(&Debug, "expand_dt_path: %s: %s\n", fieldname,val)); if (0 == strcmp(val,"none") && 0 == ptr->nlen) { /* Set dummy value indicating none ... */ ptr->list = safe_realloc(ptr->list,sizeof (ptr->list[0])); ptr->list[0] = NULL; ptr->nlen = 0; return ret; } } else { DPRINT(Debug,11,(&Debug, "expand_dt_path: %s: %s (recursive=%d)\n", fieldname,val,recursive)); } for (p = val; !quit_flag && (*p || start_val); p++) { char * value = NULL; /* Quarantee that we do not advance bast of \0 */ quit_flag = !*p; /* Recognize \ escape only in quoted strings */ if (q && '\\' == *p) { p++; if (!*p) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmTrailingBackslashInElmrc, "Trailing backslash (\\) on key \"%s\" value \"%s\""), fieldname,val); ret = 0; } continue; } if (!start_val) { if (q || !*p) { panic("RC PANIC",__FILE__,__LINE__,"expand_dt_path", "Bad state on !start_val",0); } if (is_quote && '"' == *p) { start_val = p+1; q = '"'; continue; } if (is_quote_single && '\'' == *p) { start_val = p+1; q = '\''; continue; } /* Empty values not allowed */ if (is_sep_comma && ',' == *p || is_sep_colon && ':' == *p || is_sep_space && ' ' == *p || is_sep_space && '\t' == *p) continue; start_val = p; } else if (q) { if (q == *p || '\0' == *p) { int Len = p - start_val; char * t, *s; if (!*p) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmUnbalancedQuoteInElmrc, "Unbalanced quote (%c) on key \"%s\" value \"%s\""), q,fieldname,val); ret = 0; } DPRINT(Debug,11,(&Debug, "expand_dt_path (clip len=%d)=%.*s\n", Len,Len,start_val)); value = safe_malloc( Len +1 ); for (s = start_val, t = value; t-value < Len && s < p;) { if ('\\' == *s) s++; *t++ = *s++; } *t = '\0'; q = 0; DPRINT(Debug,11,(&Debug, "expand_dt_path (unquoted)=%s\n", value)); start_val = NULL; goto expand_value; } } else { if (is_sep_comma && ',' == *p || is_sep_colon && ':' == *p || is_sep_space && ' ' == *p || is_sep_space && '\t' == *p || '\0' == *p ) { int Len = p - start_val; DPRINT(Debug,11,(&Debug, "expand_dt_path (clip len=%d)=%.*s\n", Len,Len,start_val)); value = safe_malloc( Len +1 ); memcpy(value,start_val,Len); value[Len] = '\0'; if (convert_underline) { int i; for (i = 0; i < Len; i++) if ('_' == value[i]) value[i] = ' '; } start_val = NULL; goto expand_value; } if (is_quote && '"' == *p) { int Len = p - start_val; /* Split on quote */ q = '"'; DPRINT(Debug,11,(&Debug, "expand_dt_path (clip len=%d)=%.*s\n", Len,Len,start_val)); value = safe_malloc( Len +1 ); memcpy(value,start_val,Len); value[Len] = '\0'; start_val = NULL; goto expand_value; } if (is_quote_single && '\'' == *p) { int Len = p - start_val; /* Split on quote */ q = '\''; DPRINT(Debug,11,(&Debug, "expand_dt_path (clip len=%d)=%.*s\n", Len,Len,start_val)); value = safe_malloc( Len +1 ); memcpy(value,start_val,Len); value[Len] = '\0'; start_val = NULL; goto expand_value; } } if (0) { expand_value: if (is_expand) { char buffer[1024]; int v = expand_path(buffer,value,sizeof buffer); if (v < 0) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadVariableInElmrc, "Bad variable on key \"%s\" value \"%s\""), fieldname,val); ret = 0; } else if (v > 0) { DPRINT(Debug,11,(&Debug, "expand_dt_path (expanded)=%s\n", buffer)); if (recursive < 2 && (is_sep_colon || is_sep_comma)) { if (!expand_dt_path(ptr,fieldname,buffer,recursive+1)) ret = 0; free(value); value = NULL; continue; } value = strmcpy(value,buffer); } } if (is_file || is_dir) { struct stat S; if ('/' != value[0]) { if (0 == recursive) { DPRINT(Debug,9,(&Debug, "expand_dt_path not absolute=%s\n", value)); lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNotAbsoluteInElmrc, "Path component \"%s\" not absolute on key \"%s\" value \"%s\""), value,fieldname,val); ret = 0; } free(value); value = NULL; continue; } if (-1 == stat(value,&S)) { DPRINT(Debug,9,(&Debug, "expand_dt_path not accessib=%s\n", value)); if (0 == recursive) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNotAccessibleInElmrc, "Path component \"%s\" not accessible on key \"%s\" value \"%s\""), value,fieldname,val); ret = 0; } free(value); value = NULL; continue; } if (is_dir && #ifdef S_ISDIR !S_ISDIR(S.st_mode) #else S_IFDIR != (S.st_mode & S_IFMT) #endif ) { DPRINT(Debug,9,(&Debug, "expand_dt_path not director=%s\n", value)); if (0 == recursive) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNotDirInElmrc, "Path component \"%s\" not a directory on key \"%s\" value \"%s\""), value,fieldname,val); ret = 0; } free(value); value = NULL; continue; } if (is_file && #ifdef S_ISREG !S_ISREG(S.st_mode) #else S_IFREG != (S.st_mode & S_IFMT) #endif ) { DPRINT(Debug,9,(&Debug, "expand_dt_path not a file =%s\n", value)); if (0 == recursive) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNotFileInElmrc, "Path component \"%s\" not a file on key \"%s\" value \"%s\""), value,fieldname,val); ret = 0; } free(value); value = NULL; continue; } } DPRINT(Debug,9,(&Debug, "expand_dt_path [%d]=%s\n", ptr->nlen,value)); ptr->list = safe_realloc(ptr->list, (ptr->nlen+1)* sizeof (ptr->list[0])); ptr->list[ptr->nlen++] = value; if (q) { DPRINT(Debug,9,(&Debug, "expand_dt_path : Starting next quoted value...\n")); start_val = p+1; } } } if (start_val || q) { panic("RC PANIC",__FILE__,__LINE__,"expand_dt_path", "Bad state on end",0); } if (!recursive) { DPRINT(Debug,9,(&Debug, "expand_dt_path=%d\n", ret)); } else { DPRINT(Debug,11,(&Debug, "expand_dt_path=%d (recursive=%d)\n", ret,recursive)); } if (ptr->nlen > 0) { /* Add trailing NULL */ ptr->list = safe_realloc(ptr->list, (ptr->nlen+1)* sizeof (ptr->list[0])); ptr->list[ptr->nlen] = NULL; } return ret; } char ** give_dt_path_as_elems(ptr, fieldname) struct dt_path_info *ptr; char * fieldname; { if (!ptr->list && ptr->unexpanded) expand_dt_path(ptr,fieldname,ptr->unexpanded,0); return ptr->list; } char * give_dt_path_as_str(ptr,fieldname) struct dt_path_info *ptr; char * fieldname; { char *res,*p; int sep; int quote; int i,L = 1; if (!ptr->list && ptr->unexpanded) expand_dt_path(ptr,fieldname,ptr->unexpanded,0); if (!ptr->list) return NULL; if (ptr->list && 0 == ptr->nlen) { res = safe_strdup("none"); DPRINT(Debug,9,(&Debug, "give_dt_path_as_str=%s\n",res)); return res; } for (i = 0; i < ptr->nlen; i++) L += strlen(ptr->list[i]) +1; if (ptr->flags & PATH_sep_comma) sep = ','; else if (ptr->flags & PATH_sep_colon) sep = ':'; else sep = ' '; if (ptr->flags & PATH_quote) quote = '"'; else if (ptr->flags & PATH_quote_single) quote = '\''; else quote = 0; if (quote) L += ptr->nlen * 2; res = safe_malloc(L); for (i = 0, p = res; i < ptr->nlen;i++) { int l = strlen(ptr->list[i]); if (p+l+1 + (quote ? 2 : 0) >= res+L) panic("RC PANIC",__FILE__,__LINE__,"give_dt_path_as_str", "Overflow",0); if (i > 0) *p++ = sep; if (quote) *p++ = quote; memcpy(p,ptr->list[i],l); p += l; if (quote) *p++ = quote; } *p = '\0'; DPRINT(Debug,9,(&Debug, "give_dt_path_as_str (len=%d)=%s\n",L,res)); return res; } #if ANSI_C static rc_parse_line dt_PATH_parse_line; #endif static int dt_PATH_parse_line(r,lcl,value,lineno,filename,negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { 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; } r->val.path->unexpanded = strmcpy(r->val.path->unexpanded,value); /* Free old value */ if (r->val.path->list) { int i; for (i = 0; i < r->val.path->nlen; i++) { if (r->val.path->list[i]) { r->val.path->list[i] = NULL; } } free(r->val.path->list); } r->val.path->list = NULL; r->val.path->nlen = 0; return 1; } #if ANSI_C static rc_parse_cline dt_PATH_parse_cline; #endif static int dt_PATH_parse_cline(r,lcl,value,lineno,filename) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; { int ret = 1; /* First line is unexpanded so expand it .... */ if (r->val.path->unexpanded) { ret = expand_dt_path(r->val.path, r->name,r->val.path->unexpanded,0); if (!ret) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadValueInElmrc, "Value of \"%s\" in line %d in \"%s\" file is bad"), r->name,lineno-1,filename); } free(r->val.path->unexpanded); r->val.path->unexpanded = NULL; } if (!expand_dt_path(r->val.path,r->name,value,0)) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadValueInElmrc, "Value of \"%s\" in line %d in \"%s\" file is bad"), r->name,lineno,filename); ret = 0; } return ret; } #if ANSI_C static rc_print_value dt_PATH_print_value; #endif static void dt_PATH_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { if (r->val.path->unexpanded) { if (comment) fprintf(F, "### "); fprintf(F, "%s = %s\n", r->name, r->val.path->unexpanded); } else { int i; int len = strlen(r->name) + 3; if (comment) fprintf(F, "### "); fprintf(F, "%s = ",r->name); if (r->val.path->list && 0 == r->val.path->nlen) { fprintf(F, "none"); } for (i = 0; i < r->val.path->nlen; i++) { /* NOTE: space is always valid separator even when PATH_sep_comma or PATH_sep_colon is set */ if (i > 0) { if (len + strlen(r->val.path->list[i]) > 70) { fprintf(F, "\n"); if (comment) fprintf(F, "### "); fprintf(F, "\t"); len = 8; } else fprintf(F, " "); } if (r->val.path->flags & PATH_quote) elm_fprintf(F,FRM("%Q"),r->val.path->list[i]); else if (r->val.path->flags & PATH_quote_single) { fputc('\'',F); fputs(r->val.path->list[i],F); fputc('\'',F); } else fputs(r->val.path->list[i],F); len += strlen(r->val.path->list[i]) + 1; } fprintf(F, "\n"); } } struct rc_type rc_DT_PATH = { RCTYPE_magic, dt_PATH_parse_line, dt_PATH_parse_cline, dt_PATH_print_value, NO_get_value }; #ifdef ANSI_C static rc_parse_line dt_OBS_parse_line; #endif static int dt_OBS_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { /* This message is not perhaps very visible, because ELm starts anyway, but it was requested on that way. */ lib_error(CATGETS(elm_msg_cat, ElmSet, ElmObsoleteInElmrc, "Elmrc variable \"%s\" is obsolete and should be removed from line %d in \"%s\" file"), r->name,lineno,filename); return 1; /* Mark as succeed */ } struct rc_type rc_DT_OBS = { RCTYPE_magic, dt_OBS_parse_line, BAD_parse_cline, NO_print_value, NO_get_value }; static void metamail_expand(struct dt_estr_info *ptr); static void metamail_expand(ptr) struct dt_estr_info *ptr; { if (getenv("NOMETAMAIL")) { if (ptr->expanded) free(ptr->expanded); ptr->expanded = NULL; } else { ptr->expanded = strmcpy(ptr->expanded,"metamail"); } } /* 0 == failure 1 == succeed */ static void estr_set_expanded P_((struct dt_estr_info *ptr, const char *buffer)); static void estr_set_expanded(ptr,buffer) struct dt_estr_info *ptr; CONST char *buffer; { /* Fix shell if needed */ if (ptr->flags & ESTR_bin) { if (buffer[0] != '/') { char * A = elm_message(FRM("/bin/%s"), buffer); if (ptr->expanded) free(ptr->expanded); ptr->expanded = A; return; } } ptr->expanded = strmcpy(ptr->expanded,buffer); /* Fix temp_dir if needed */ if (ptr->flags & ESTR_slash) { int l = strlen(buffer); if (0 == l || buffer[l-1] != '/') ptr->expanded = strmcat(ptr->expanded,"/"); } } int expand_dt_estr(ptr,fieldname,val) struct dt_estr_info *ptr; char *fieldname; char *val; { char buffer[1024]; int x; if (ptr->flags & ESTR_none) { if (0 == strcmp("none",ptr->unexpanded)) { if (ptr->expanded) free(ptr->expanded); ptr->expanded = NULL; return 1; } } if (ptr->flags & ESTR_metamail) { if (0 == strcmp("metamail",ptr->unexpanded)) { metamail_expand(ptr); return 1; } } if (ptr->flags & ESTR_meta) x = expand_meta(buffer, ptr->unexpanded, sizeof buffer); else x = expand_env(buffer, ptr->unexpanded, sizeof buffer); if (x != 0) { lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadVariableInElmrc, "Bad variable on key \"%s\" value \"%s\""), fieldname,val); return 0; } estr_set_expanded(ptr,buffer); return 1; } /* Retuns 1 if sepecial value "none" */ int dt_estr_is_disabled(ptr) struct dt_estr_info *ptr; { if (ptr->flags & ESTR_none) { if (0 == strcmp("none",ptr->unexpanded)) { return 1; } } return 0; } char * give_dt_estr_as_str(ptr,fieldname) struct dt_estr_info *ptr; char * fieldname; { if (!ptr->expanded && ptr->unexpanded) expand_dt_estr(ptr,fieldname,ptr->unexpanded); return ptr->expanded; } /* Set initial value */ extern void set_dt_estr(ptr, const_val, def_env) struct dt_estr_info *ptr; CONST char *const_val; char *def_env; { char *cp; if (def_env && (cp = getenv(def_env)) && cp[0]) { char *x = elm_message(FRM("$%s"),def_env); ptr->unexpanded = strmcpy(ptr->unexpanded,x); estr_set_expanded(ptr,cp); free(x); } else { if (ptr->flags & ESTR_none) { if (0 == strcmp("none",const_val)) { ptr->unexpanded = strmcpy(ptr->unexpanded,const_val); if (ptr->expanded) free(ptr->expanded); ptr->expanded = NULL; return; } } if (ptr->flags & ESTR_metamail) { if (0 == strcmp("metamail",const_val)) { ptr->unexpanded = strmcpy(ptr->unexpanded,const_val); metamail_expand(ptr); return; } } ptr->unexpanded = strmcpy(ptr->unexpanded,const_val); estr_set_expanded(ptr,const_val); } } #ifdef ANSI_C static rc_parse_line dt_ESTR_parse_line; #endif static int dt_ESTR_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { 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; } r->val.estr->unexpanded = strmcpy(r->val.estr->unexpanded,value); /* Free old value */ if (r->val.estr->expanded) { free(r->val.estr->expanded); r->val.estr->expanded = NULL; } return 1; } #if ANSI_C static rc_get_value dt_ESTR_get_value; #endif static char * dt_ESTR_get_value(r) struct rc_save_info_rec *r; { return r->val.estr->unexpanded; } #if ANSI_C static rc_print_value dt_ESTR_print_value; #endif static void dt_ESTR_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { if (r->val.estr->unexpanded) { if (comment) fprintf(F, "### "); fprintf(F, "%s = %s\n", r->name, r->val.estr->unexpanded); } else { fprintf(F, "### %s (not set)\n", r->name); } } struct rc_type rc_DT_ESTR = { RCTYPE_magic, dt_ESTR_parse_line, BAD_parse_cline, dt_ESTR_print_value, dt_ESTR_get_value }; int give_dt_enumerate_as_int(ptr) struct dt_enumerate_info *ptr; { return ptr->val; } CONST char * give_dt_enumerate_as_str(ptr) struct dt_enumerate_info *ptr; { static char * buffer = NULL; if (ptr->val >= 0 && ptr->val < ptr->nlen) return ptr->list[ptr->val]; if (buffer) free(buffer); buffer = elm_message(FRM("%d"), ptr->val); return buffer; } int set_dt_enumerate_as_str(ptr,str) struct dt_enumerate_info *ptr; char *str; { int ci = -1, i; int e_val; e_val = 0; /* First value is 'unknown' */ for (i = 0; i < ptr->nlen; i++) if (0 == strcmp(ptr->list[i],str)) { e_val = i; break; } else if (0 == istrcmp(ptr->list[i],str)) ci = i; if (!e_val && ci >= 0) e_val = ci; if (i == ptr->nlen) { char *p; if ((e_val = strtol(str,&p,10)) < 0 || *p != '\0') return 0; } ptr->val = e_val; return 1; } #ifdef ANSI_C static rc_parse_line dt_ENUM_parse_line; #endif static int dt_ENUM_parse_line(r,lcl,value,lineno,filename, negate) struct rc_save_info_rec *r; int lcl; char *value; int lineno; char *filename; int negate; { 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 (!set_dt_enumerate_as_str(r->val.enumerate,value)) { int i; lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadEKeyInElmrc, "I can't understand %s key \"%s\" in line %d in \"%s\" file"), r->name,value, lineno,filename); lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadEKeyValues, "Possible values are:")); for (i = 0; i < r->val.enumerate->nlen; i++) lib_error(FRM(" - %s"), r->val.enumerate->list[i]); return 0; } return 1; } #if ANSI_C static rc_get_value dt_ENUM_get_value; #endif static char * dt_ENUM_get_value(r) struct rc_save_info_rec *r; { static char * buffer = NULL; if (r->val.enumerate->val >= 0 && r->val.enumerate->val < r->val.enumerate->nlen) return r->val.enumerate->list[r->val.enumerate->val]; if (buffer) free(buffer); buffer = elm_message(FRM("%d"), r->val.enumerate->val); return buffer; } #if ANSI_C static rc_print_value dt_ENUM_print_value; #endif static void dt_ENUM_print_value(F,r,comment) FILE *F; struct rc_save_info_rec *r; int comment; { if (comment) fprintf(F, "### "); if (r->val.enumerate->val >= 0 && r->val.enumerate->val < r->val.enumerate->nlen) { char * s = r->val.enumerate->list[r->val.enumerate->val]; fprintf(F, "%s = %s\n", r->name, s); DPRINT(Debug,9,(&Debug, " option \"%s\", value=\"%s\"\n", r->name,s )); } else { fprintf(F, "%s = %d\n", r->name, r->val.enumerate->val); DPRINT(Debug,9,(&Debug, " option \"%s\", value=%d\n", r->name,r->val.enumerate->val )); } } struct rc_type rc_DT_ENUM = { RCTYPE_magic, dt_ENUM_parse_line, BAD_parse_cline, dt_ENUM_print_value, dt_ENUM_get_value }; /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */