ftp.nice.ch/pub/next/unix/mail/elm2.4/elm.2.4pl17.s.tar.gz#/src/save_opts.c

This is save_opts.c in view mode; [Download] [Up]

static char rcsid[] = "@(#)$Id: save_opts.c,v 5.1 1992/10/03 22:58:40 syd Exp $";

/*******************************************************************************
 *  The Elm Mail System  -  $Revision: 5.1 $   $State: Exp $
 *
 *			Copyright (c) 1988-1992 USENET Community Trust
 *			Copyright (c) 1986,1987 Dave Taylor
 *******************************************************************************
 * Bug reports, patches, comments, suggestions should be sent to:
 *
 *	Syd Weinstein, Elm Coordinator
 *	elm@DSI.COM			dsinc!elm
 *
 *******************************************************************************
 * $Log: save_opts.c,v $
 * Revision 5.1  1992/10/03  22:58:40  syd
 * Initial checkin as of 2.4 Release at PL0
 *
 *
 ******************************************************************************/

/** This file contains the routine needed to allow the users to change the
    Elm parameters and then save the configuration in a ".elm/elmrc" file in
    their home directory.  With any luck this will allow them never to have
    to actually EDIT the file!!

**/

#include "headers.h"
#include "s_elmrc.h"
#include <errno.h>

#undef onoff
#define   onoff(n)	(n == 1? "ON":"OFF")

#define absolute(x)		((x) < 0? -(x) : (x))

extern  int errno;
extern char version_buff[];

char *error_description(), *sort_name(), *alias_sort_name(), *level_name();
long  ftell();

#include "save_opts.h"

FILE *elminfo;		/* informational file as needed... */

save_options()
{
	/** Save the options currently specified to a file.  This is a
	    fairly complex routine since it tries to put in meaningful
	    comments and such as it goes along.  The comments are
	    extracted from the file ELMRC_INFO as defined in the sysdefs.h
	    file.  THAT file has the format;

		varname
		  <comment>
		  <comment>
		<blank line>

	    and each comment is written ABOVE the variable to be added.  This
	    program also tries to make 'pretty' stuff like the alternatives
	    and such.
	**/

	FILE *newelmrc; 
	char  oldfname[SLEN], newfname[SLEN];

	sprintf(newfname, "%s/%s", home, elmrcfile);
	sprintf(oldfname, "%s/%s", home, old_elmrcfile);

	/** first off, let's see if they already HAVE a .elm/elmrc file **/

	save_file_stats(newfname);
	if (access(newfname, ACCESS_EXISTS) != -1) {
	  /** YES!  Copy it to the file ".old.elmrc".. **/
	  if (rename(newfname, oldfname) < 0)
	    dprint(2, (debugfile, "Unable to rename %s to %s\n", 
		   newfname, oldfname));
	  (void) chown(oldfname, userid, groupid);

	}

	/** now let's open the datafile if we can... **/

	if ((elminfo = fopen(ELMRC_INFO, "r")) == NULL) 
	  error1(catgets(elm_msg_cat, ElmrcSet, ElmrcSavingWithoutComments,
		  "Warning: saving without comments! Can't get to %s."), 
		  ELMRC_INFO);

	/** next, open the new .elm/elmrc file... **/

	if ((newelmrc = fopen(newfname, "w")) == NULL) {
	   error2(catgets(elm_msg_cat, ElmrcSet, ElmrcCantSaveConfig,
		   "Can't save configuration! Can't write to %s [%s]."),
		   newfname, error_description(errno));
	   return;
	}
	
	save_user_options(elminfo, newelmrc);
	restore_file_stats(newfname);

	error1(catgets(elm_msg_cat, ElmrcSet, ElmrcOptionsSavedIn,
		"Options saved in file %s."), newfname);
}

static char *str_opt(x, f)
register int x;
int f;
{
	static char buf[SLEN];
	register char *s, *t;

	s = strcpy(buf, "*ERROR*");
	switch(save_info[x].flags & DT_MASK) {
	    case DT_STR:
		if (save_info[x].flags & FL_NOSPC) {
		    for (t = SAVE_INFO_STR(x), s = buf; *t; ++t, ++s)
			if ((*s = *t) == SPACE) *s='_';
		    *s = '\0';
		    s = buf;
		} else
		    s = SAVE_INFO_STR(x);
		break;

	    case DT_CHR:
		sprintf(buf, "%c", *SAVE_INFO_CHR(x));
		s = buf;
		break;

	    case DT_BOL:
		s = onoff(*SAVE_INFO_BOL(x));
		break;

	    case DT_SRT:
		if (f == FULL) {
		    s = sort_name(SHORT);
		    break;
		}
		sprintf(buf, "%d", *SAVE_INFO_NUM(x));
		s = buf;
		break;

	    case DT_ASR:
		if (f == FULL) {
		    s = alias_sort_name(SHORT);
		    break;
		}
		sprintf(buf, "%d", *SAVE_INFO_NUM(x));
		s = buf;
		break;

	    case DT_NUM:
		if (f == FULL) {
		    if (equal(save_info[x].name, "userlevel")) {
			s = level_name(*SAVE_INFO_NUM(x));
			break;
		    }
		}
		sprintf(buf, "%d", *SAVE_INFO_NUM(x));
		s = buf;
		break;

	    default:
		break;
	}
	return(s);
}

find_opt(s)
char *s;
{
	register int x, y;

	for (x = 0; x < NUMBER_OF_SAVEABLE_OPTIONS; x++) {
	    y = strcmp(s, save_info[x].name);
	    if (y <= 0)
		break;
	}

	if (y != 0)
	    return(-1);
	return(x);
}

char *str_opt_nam(s, f)
char *s;
int f;
{
	char *t = NULL;
	int x;

	x = find_opt(s);
	if (x >= 0)
	    t = str_opt(x, f);
	return(t);
}


save_user_options(elminfo_fd, newelmrc)
FILE *elminfo_fd, *newelmrc;
{
	register int x, local_value;
	register char *s;

	/** save the information in the file.  If elminfo_fd == NULL don't look
	    for comments!
	**/

	if (elminfo_fd != NULL) 
	  build_offset_table(elminfo_fd);

	fprintf(newelmrc, catgets(elm_msg_cat, ElmrcSet, ElmrcOptionsFile,
	      "#\n# .elm/elmrc - options file for the ELM mail system\n#\n"));

	if (strlen(full_username) > 0)
	  MCfprintf(newelmrc, catgets(elm_msg_cat, ElmrcSet, ElmrcSavedAutoFor,
		  "# Saved automatically by ELM %s for %s\n#\n\n"),
		  version_buff, full_username);
	else
	  fprintf(newelmrc, catgets(elm_msg_cat, ElmrcSet, ElmrcSavedAuto,
		"# Saved automatically by ELM %s\n#\n\n"), version_buff);

	fprintf(newelmrc, catgets(elm_msg_cat, ElmrcSet, ElmrcYesNoMeans,
		"# For yes/no settings with ?, ON means yes, OFF means no\n"));

	for (x = 0; x < NUMBER_OF_SAVEABLE_OPTIONS; x++) {
	    char buf[SLEN];

	    /** skip system-only options **/
	    if (save_info[x].flags & FL_SYS)
		continue;

	    local_value = save_info[x].flags & FL_LOCAL;
	    s="";
	    switch(save_info[x].flags & DT_MASK) {
		case DT_MLT:
		case DT_SYN:
		    break;

		case DT_ASR:
		case DT_SRT:
		    s = str_opt(x, FULL);
		    break;

		case DT_STR:
		case DT_CHR:
		case DT_BOL:
		case DT_NUM:
		    s = str_opt(x, SHORT);
		    break;

		case DT_WEE:
		    { int len = 0 ,i;

			add_comment(x, newelmrc);
			if (!local_value)
			    fprintf(newelmrc, "### ");
			fprintf(newelmrc, "%s = ", save_info[x].name);
			len = strlen(save_info[x].name) + 4;

			for (i = 0; i < weedcount && strcmp(weedlist[i], "*end-of-defaults*") !=0; i++)
			    /* intentional null loop body */;

			while (i < weedcount && equal(weedlist[i], "*end-of-defaults*"))
			    i++;

			while (i < weedcount) {
			    if (strlen(weedlist[i]) + len > 78) {
				if (local_value)
				    fprintf(newelmrc, "\n\t");
				else
				    fprintf(newelmrc, "\n###\t");
				len = 8;
			    }
			    fprintf(newelmrc, "\"%s\" ", weedlist[i]);
			    len += strlen(weedlist[i]) + 4;
			    ++i;
			}
			fprintf(newelmrc, "\t\"*end-of-user-headers*\"\n");
		    }
		    break;

		case DT_ALT:
		    {   struct addr_rec *alts;
			int len=0;

			alts = *SAVE_INFO_ALT(x);
			if (!alts) break;

			add_comment(x, newelmrc);
			if (!local_value)
			    fprintf(newelmrc, "### ");
			fprintf(newelmrc, "%s = ", save_info[x].name);
			len = strlen(save_info[x].name) + 4;
			for ( ;alts; alts = alts->next) {
			    if (strlen(alts->address) + len > 78) {
				if (local_value)
				    fprintf(newelmrc, "\n\t");
				else
				    fprintf(newelmrc, "\n###\t");
				len = 8;
			    }
			fprintf(newelmrc, "%s ", alts->address);
			len += strlen(alts->address) + 2;
			}
		    }
		    fprintf(newelmrc,"\n");
		    break;
		}

	    if (*s) {
		add_comment(x, newelmrc);
		if (local_value)
		    fprintf(newelmrc, "%s = %s\n", save_info[x].name, s);
		else
		    fprintf(newelmrc, "### %s = %s\n", save_info[x].name, s);
		}
	    }

	fclose(newelmrc);
	if ( elminfo_fd != NULL ) {
	    fclose(elminfo_fd);
	}
}

add_comment(iindex, fd)
int iindex;
FILE *fd;
{	
	/** get to and add the comment to the file **/
	char buffer[SLEN];

	/** always put a blank line between options */
	fputc('\n', fd);

	/** add the comment from the comment file, if available **/
	if (save_info[iindex].offset > 0L) {
	  if (fseek(elminfo, save_info[iindex].offset, 0) == -1) {
	    dprint(1,(debugfile,
		   "** error %s seeking to %ld in elm-info file!\n",
		   error_description(errno), save_info[iindex].offset));
	  }
	  else {
	    while (fgets(buffer, SLEN, elminfo) != NULL) {
	      if (buffer[0] != '#') 
		break;
	      fputs(buffer, fd);
	    }
	  }
	}
}

build_offset_table(elminfo_fd)
FILE *elminfo_fd;
{
	/** read in the info file and build the table of offsets.
	    This is a rather laborious puppy, but at least we can
	    do a binary search through the array for each element and
	    then we have it all at once!
	**/

	char line_buffer[SLEN];
	
	while (fgets(line_buffer, SLEN, elminfo_fd) != NULL) {
	  if (strlen(line_buffer) > 1)
	    if (line_buffer[0] != '#' && !whitespace(line_buffer[0])) {
	       no_ret(line_buffer);
	       if (find_and_store_loc(line_buffer, ftell(elminfo_fd))) {
	         dprint(1, (debugfile,"** Couldn't find and store \"%s\" **\n", 
			 line_buffer));
	       }
	    }
	}
}

find_and_store_loc(name, offset)
char *name;
long  offset;
{
	/** given the name and offset, find it in the table and store it **/

	int first = 0, last, middle, compare;

	last = NUMBER_OF_SAVEABLE_OPTIONS;

	while (first <= last) {

	  middle = (first+last) / 2;

	  if ((compare = strcmp(name, save_info[middle].name)) < 0) /* a < b */
	    last = middle - 1;
	  else if (compare == 0) {				    /* a = b */
	    save_info[middle].offset = offset;
	    return(0);
	  }
	  else  /* greater */					    /* a > b */
	    first = middle + 1; 
	}

	return(-1);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.