2001-04-18 04:28:54 +00:00
|
|
|
/* $Id$ */
|
|
|
|
/**************************************************************************
|
2001-05-05 15:02:27 +00:00
|
|
|
* rcfile.c *
|
2001-04-18 04:28:54 +00:00
|
|
|
* *
|
|
|
|
* Copyright (C) 1999 Chris Allegretta *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 1, or (at your option) *
|
|
|
|
* any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the Free Software *
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
|
|
|
* *
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include "config.h"
|
|
|
|
#include "proto.h"
|
|
|
|
#include "nano.h"
|
|
|
|
|
|
|
|
#ifdef ENABLE_NANORC
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
#include <libintl.h>
|
|
|
|
#define _(string) gettext(string)
|
|
|
|
#else
|
|
|
|
#define _(string) (string)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define NUM_RCOPTS 14
|
|
|
|
/* Static stuff for the nanorc file */
|
|
|
|
rcoption rcopts[NUM_RCOPTS] =
|
|
|
|
{
|
|
|
|
{"regexp", USE_REGEXP},
|
|
|
|
{"const", CONSTUPDATE},
|
|
|
|
{"autoindent", AUTOINDENT},
|
|
|
|
{"cut", CUT_TO_END},
|
|
|
|
{"nofollow", FOLLOW_SYMLINKS},
|
|
|
|
{"mouse", USE_MOUSE},
|
|
|
|
{"pico", PICO_MODE},
|
|
|
|
{"fill", 0},
|
|
|
|
{"speller", 0},
|
|
|
|
{"tempfile", TEMP_OPT},
|
|
|
|
{"view", VIEW_MODE},
|
|
|
|
{"nowrap", NO_WRAP},
|
|
|
|
{"nohelp", NO_HELP},
|
|
|
|
{"suspend", SUSPEND}};
|
|
|
|
|
|
|
|
/* We have an error in some part of the rcfile, put it on stderr and
|
|
|
|
make the usr hit return to continue starting up nano */
|
|
|
|
void rcfile_error(char *msg, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
va_start(ap, msg);
|
|
|
|
vfprintf(stderr, msg, ap);
|
|
|
|
va_end(ap);
|
|
|
|
fprintf(stderr, _("\nPress return to continue starting nano\n"));
|
|
|
|
|
|
|
|
while (getchar() != '\n')
|
|
|
|
;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Just print the error (one of many perhaps) but don't abort, yet */
|
|
|
|
void rcfile_msg(int *errors, char *msg, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
if (!*errors) {
|
|
|
|
*errors = 1;
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
va_start(ap, msg);
|
|
|
|
vfprintf(stderr, msg, ap);
|
|
|
|
va_end(ap);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse the next word from the string. Returns NULL of we hit EOL */
|
|
|
|
char *parse_next_word(char *ptr)
|
|
|
|
{
|
|
|
|
while (*ptr != ' ' && *ptr != '\n' && ptr != '\0')
|
|
|
|
ptr++;
|
|
|
|
|
|
|
|
if (*ptr == '\0')
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Null terminate and advance ptr */
|
|
|
|
*ptr++ = 0;
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse the RC file, once it has been opened successfully */
|
|
|
|
void parse_rcfile(FILE *rcstream, char *filename)
|
|
|
|
{
|
|
|
|
char *buf, *ptr, *keyword, *option;
|
|
|
|
int set = 0, lineno = 0, i;
|
|
|
|
int errors = 0;
|
|
|
|
|
|
|
|
buf = ncalloc(1024, sizeof(char));
|
|
|
|
while (fgets(buf, 1023, rcstream) > 0) {
|
|
|
|
lineno++;
|
|
|
|
ptr = buf;
|
|
|
|
while ((*ptr == ' ' || *ptr == '\t') &&
|
|
|
|
(*ptr != '\n' && *ptr != '\0'))
|
|
|
|
ptr++;
|
|
|
|
|
|
|
|
if (*ptr == '\n' || *ptr == '\0')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (*ptr == '#') {
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, _("parse_rcfile: Read a comment\n"));
|
|
|
|
#endif
|
|
|
|
continue; /* Skip past commented lines */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Else skip to the next space */
|
|
|
|
keyword = ptr;
|
|
|
|
ptr = parse_next_word(ptr);
|
|
|
|
if (!ptr)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Else try to parse the keyword */
|
|
|
|
if (!strcasecmp(keyword, "set"))
|
|
|
|
set = 1;
|
|
|
|
else if (!strcasecmp(keyword, "unset"))
|
|
|
|
set = -1;
|
|
|
|
else {
|
|
|
|
rcfile_msg(&errors, _("Error in %s on line %d: command %s not understood"),
|
|
|
|
filename, lineno, keyword);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
option = ptr;
|
|
|
|
ptr = parse_next_word(ptr);
|
|
|
|
/* We don't care if ptr == NULL, as it should if using proper syntax */
|
|
|
|
|
|
|
|
if (set != 0) {
|
|
|
|
for (i = 0; i <= NUM_RCOPTS - 1; i++) {
|
|
|
|
if (!strcasecmp(option, rcopts[i].name)) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "parse_rcfile: Parsing option %s\n",
|
|
|
|
rcopts[i].name);
|
|
|
|
#endif
|
|
|
|
if (set == 1 || rcopts[i].flag == FOLLOW_SYMLINKS) {
|
|
|
|
if (!strcasecmp(rcopts[i].name, "fill") ||
|
|
|
|
!strcasecmp(rcopts[i].name, "speller")) {
|
|
|
|
|
|
|
|
if (*ptr == '\n' || *ptr == '\0') {
|
|
|
|
rcfile_msg(&errors, _("Error in %s on line %d: option %s requires an argument"),
|
|
|
|
filename, lineno, rcopts[i].name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
option = ptr;
|
|
|
|
ptr = parse_next_word(ptr);
|
|
|
|
if (!strcasecmp(rcopts[i].name, "fill")) {
|
|
|
|
if ((i = atoi(option)) < MIN_FILL_LENGTH) {
|
|
|
|
rcfile_msg(&errors,
|
|
|
|
_("Error in %s on line %d: requested fill size %d too small"),
|
|
|
|
filename, lineno, option);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fill = i;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
alt_speller = ncalloc(strlen(option) + 1, sizeof(char));
|
|
|
|
strcpy(alt_speller, option);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
SET(rcopts[i].flag);
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "set flag %d!\n", rcopts[i].flag);
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
UNSET(rcopts[i].flag);
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "unset flag %d!\n", rcopts[i].flag);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if (errors)
|
|
|
|
rcfile_error(_("Errors found in .nanorc file"));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The main rc file function, tries to open the rc file */
|
|
|
|
void do_rcfile(void)
|
|
|
|
{
|
|
|
|
char *nanorc;
|
|
|
|
char *unable = _("Unable to open ~/.nanorc file, %s");
|
|
|
|
struct stat fileinfo;
|
|
|
|
FILE *rcstream;
|
|
|
|
|
|
|
|
if (getenv("HOME") == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nanorc = nmalloc(strlen(getenv("HOME")) + 10);
|
|
|
|
sprintf(nanorc, "%s/.nanorc", getenv("HOME"));
|
|
|
|
|
|
|
|
if (stat(nanorc, &fileinfo) == -1) {
|
|
|
|
|
|
|
|
/* Abort if the file doesn't exist and there's some other kind
|
|
|
|
of error stat()ing it */
|
|
|
|
if (errno != ENOENT)
|
|
|
|
rcfile_error(unable, errno);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((rcstream = fopen(nanorc, "r")) == NULL) {
|
|
|
|
rcfile_error(unable, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_rcfile(rcstream, nanorc);
|
|
|
|
fclose(rcstream);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* ENABLE_NANORC */
|
|
|
|
|