blob: 36342108b84c74e461126dc63d22964120f16f1b [file] [log] [blame]
Chris Allegretta8d8e0122001-04-18 04:28:54 +00001/* $Id$ */
2/**************************************************************************
Chris Allegrettaa9434802001-05-05 15:02:27 +00003 * rcfile.c *
Chris Allegretta8d8e0122001-04-18 04:28:54 +00004 * *
5 * Copyright (C) 1999 Chris Allegretta *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 1, or (at your option) *
9 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
22#include <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25#include <errno.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <fcntl.h>
29#include "config.h"
30#include "proto.h"
31#include "nano.h"
32
33#ifdef ENABLE_NANORC
34
35#ifndef NANO_SMALL
36#include <libintl.h>
37#define _(string) gettext(string)
38#else
39#define _(string) (string)
40#endif
41
Chris Allegretta2d7893d2001-07-11 02:08:33 +000042#define NUM_RCOPTS 15
Chris Allegretta8d8e0122001-04-18 04:28:54 +000043/* Static stuff for the nanorc file */
44rcoption rcopts[NUM_RCOPTS] =
45{
46{"regexp", USE_REGEXP},
47{"const", CONSTUPDATE},
48{"autoindent", AUTOINDENT},
49{"cut", CUT_TO_END},
50{"nofollow", FOLLOW_SYMLINKS},
51{"mouse", USE_MOUSE},
52{"pico", PICO_MODE},
Chris Allegretta6fe61492001-05-21 12:56:25 +000053
54#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta8d8e0122001-04-18 04:28:54 +000055{"fill", 0},
Chris Allegretta6fe61492001-05-21 12:56:25 +000056#endif
57
Chris Allegretta8d8e0122001-04-18 04:28:54 +000058{"speller", 0},
59{"tempfile", TEMP_OPT},
60{"view", VIEW_MODE},
61{"nowrap", NO_WRAP},
62{"nohelp", NO_HELP},
Chris Allegretta2d7893d2001-07-11 02:08:33 +000063{"suspend", SUSPEND},
64{"loadoninsert", LOADONINSERT}};
Chris Allegretta8d8e0122001-04-18 04:28:54 +000065
Chris Allegretta88520c92001-05-05 17:45:54 +000066/* We have an error in some part of the rcfile; put it on stderr and
67 make the user hit return to continue starting up nano */
Chris Allegretta8d8e0122001-04-18 04:28:54 +000068void rcfile_error(char *msg, ...)
69{
70 va_list ap;
71
72 fprintf(stderr, "\n");
73 va_start(ap, msg);
74 vfprintf(stderr, msg, ap);
75 va_end(ap);
76 fprintf(stderr, _("\nPress return to continue starting nano\n"));
77
78 while (getchar() != '\n')
79 ;
80
81}
82
Chris Allegretta88520c92001-05-05 17:45:54 +000083/* Just print the error (one of many, perhaps) but don't abort, yet */
Chris Allegretta8d8e0122001-04-18 04:28:54 +000084void rcfile_msg(int *errors, char *msg, ...)
85{
86 va_list ap;
87
88 if (!*errors) {
89 *errors = 1;
90 fprintf(stderr, "\n");
91 }
92 va_start(ap, msg);
93 vfprintf(stderr, msg, ap);
94 va_end(ap);
95 fprintf(stderr, "\n");
96
97}
98
Chris Allegretta88520c92001-05-05 17:45:54 +000099/* Parse the next word from the string. Returns NULL if we hit EOL */
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000100char *parse_next_word(char *ptr)
101{
102 while (*ptr != ' ' && *ptr != '\n' && ptr != '\0')
103 ptr++;
104
105 if (*ptr == '\0')
106 return NULL;
107
108 /* Null terminate and advance ptr */
109 *ptr++ = 0;
110
111 return ptr;
112}
113
114/* Parse the RC file, once it has been opened successfully */
115void parse_rcfile(FILE *rcstream, char *filename)
116{
117 char *buf, *ptr, *keyword, *option;
118 int set = 0, lineno = 0, i;
119 int errors = 0;
120
Chris Allegretta8d848af2001-05-18 04:44:16 +0000121 buf = charalloc(1024);
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000122 while (fgets(buf, 1023, rcstream) > 0) {
123 lineno++;
124 ptr = buf;
125 while ((*ptr == ' ' || *ptr == '\t') &&
126 (*ptr != '\n' && *ptr != '\0'))
127 ptr++;
128
129 if (*ptr == '\n' || *ptr == '\0')
130 continue;
131
132 if (*ptr == '#') {
133#ifdef DEBUG
134 fprintf(stderr, _("parse_rcfile: Read a comment\n"));
135#endif
136 continue; /* Skip past commented lines */
137 }
138
139 /* Else skip to the next space */
140 keyword = ptr;
141 ptr = parse_next_word(ptr);
142 if (!ptr)
143 continue;
144
145 /* Else try to parse the keyword */
146 if (!strcasecmp(keyword, "set"))
147 set = 1;
148 else if (!strcasecmp(keyword, "unset"))
149 set = -1;
150 else {
151 rcfile_msg(&errors, _("Error in %s on line %d: command %s not understood"),
152 filename, lineno, keyword);
153 continue;
154 }
155
156 option = ptr;
157 ptr = parse_next_word(ptr);
158 /* We don't care if ptr == NULL, as it should if using proper syntax */
159
160 if (set != 0) {
161 for (i = 0; i <= NUM_RCOPTS - 1; i++) {
162 if (!strcasecmp(option, rcopts[i].name)) {
163#ifdef DEBUG
Jordi Mallachb4d6ad02001-05-24 13:10:06 +0000164 fprintf(stderr, _("parse_rcfile: Parsing option %s\n"),
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000165 rcopts[i].name);
166#endif
167 if (set == 1 || rcopts[i].flag == FOLLOW_SYMLINKS) {
Chris Allegretta6fe61492001-05-21 12:56:25 +0000168 if (
169#ifndef DISABLE_WRAPJUSTIFY
170 !strcasecmp(rcopts[i].name, "fill") ||
171#endif
172#ifndef DISABLE_SPELLER
173 !strcasecmp(rcopts[i].name, "speller")
174#else
175 0
176#endif
177 ) {
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000178
179 if (*ptr == '\n' || *ptr == '\0') {
180 rcfile_msg(&errors, _("Error in %s on line %d: option %s requires an argument"),
181 filename, lineno, rcopts[i].name);
182 continue;
183 }
184 option = ptr;
185 ptr = parse_next_word(ptr);
186 if (!strcasecmp(rcopts[i].name, "fill")) {
Chris Allegretta6fe61492001-05-21 12:56:25 +0000187#ifndef DISABLE_WRAPJUSTIFY
188
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000189 if ((i = atoi(option)) < MIN_FILL_LENGTH) {
190 rcfile_msg(&errors,
191 _("Error in %s on line %d: requested fill size %d too small"),
192 filename, lineno, option);
193 }
194 else
195 fill = i;
Chris Allegretta6fe61492001-05-21 12:56:25 +0000196#endif
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000197 }
198 else {
Chris Allegretta6fe61492001-05-21 12:56:25 +0000199#ifndef DISABLE_SPELLER
Chris Allegretta8d848af2001-05-18 04:44:16 +0000200 alt_speller = charalloc(strlen(option) + 1);
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000201 strcpy(alt_speller, option);
Chris Allegretta6fe61492001-05-21 12:56:25 +0000202#endif
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000203 }
204 } else
205 SET(rcopts[i].flag);
206#ifdef DEBUG
Jordi Mallachb4d6ad02001-05-24 13:10:06 +0000207 fprintf(stderr, _("set flag %d!\n"), rcopts[i].flag);
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000208#endif
209 } else {
210 UNSET(rcopts[i].flag);
211#ifdef DEBUG
Jordi Mallachb4d6ad02001-05-24 13:10:06 +0000212 fprintf(stderr, _("unset flag %d!\n"), rcopts[i].flag);
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000213#endif
214 }
215 }
216 }
217 }
218
219 }
220 if (errors)
221 rcfile_error(_("Errors found in .nanorc file"));
222
223 return;
224}
225
226/* The main rc file function, tries to open the rc file */
227void do_rcfile(void)
228{
229 char *nanorc;
230 char *unable = _("Unable to open ~/.nanorc file, %s");
231 struct stat fileinfo;
232 FILE *rcstream;
233
234 if (getenv("HOME") == NULL)
235 return;
236
Chris Allegretta88b09152001-05-17 11:35:43 +0000237 nanorc = charalloc(strlen(getenv("HOME")) + 10);
Chris Allegretta8d8e0122001-04-18 04:28:54 +0000238 sprintf(nanorc, "%s/.nanorc", getenv("HOME"));
239
240 if (stat(nanorc, &fileinfo) == -1) {
241
242 /* Abort if the file doesn't exist and there's some other kind
243 of error stat()ing it */
244 if (errno != ENOENT)
245 rcfile_error(unable, errno);
246 return;
247 }
248
249 if ((rcstream = fopen(nanorc, "r")) == NULL) {
250 rcfile_error(unable, strerror(errno));
251 return;
252 }
253
254 parse_rcfile(rcstream, nanorc);
255 fclose(rcstream);
256
257}
258
259
260#endif /* ENABLE_NANORC */
261