rcfile.c 15.7 KB
Newer Older
1
2
/* $Id$ */
/**************************************************************************
3
 *   rcfile.c                                                             *
4
 *                                                                        *
5
 *   Copyright (C) 1999-2002 Chris Allegretta                             *
6
7
 *   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 *
8
 *   the Free Software Foundation; either version 2, or (at your option)  *
9
10
11
12
13
14
15
16
17
18
19
20
21
 *   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.            *
 *                                                                        *
 **************************************************************************/

22
23
#include "config.h"

24
#include <stdlib.h>
25
#include <stdarg.h>
26
27
28
#include <string.h>
#include <stdio.h>
#include <errno.h>
Chris Allegretta's avatar
Chris Allegretta committed
29
30
#include <unistd.h>
#include <pwd.h>
31
32
33
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
Chris Allegretta's avatar
Chris Allegretta committed
34
#include <assert.h>
35
36
37
38
39
#include "proto.h"
#include "nano.h"

#ifdef ENABLE_NANORC

40
const static rcoption rcopts[] = {
41
#ifndef NANO_SMALL
42
    {"autoindent", AUTOINDENT},
43
44
45
46
    {"backup", BACKUP_FILE},
#endif
    {"const", CONSTUPDATE},
#ifndef NANO_SMALL
47
    {"cut", CUT_TO_END},
48
#endif
Chris Allegretta's avatar
Chris Allegretta committed
49
#ifndef DISABLE_WRAPJUSTIFY
50
    {"fill", 0},
Chris Allegretta's avatar
Chris Allegretta committed
51
#endif
52
    {"keypad", ALT_KEYPAD},
53
#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
54
    {"mouse", USE_MOUSE},
55
56
57
58
59
60
61
#endif
#ifdef ENABLE_MULTIBUFFER
    {"multibuffer", MULTIBUFFER},
#endif
#ifndef NANO_SMALL
    {"noconvert", NO_CONVERT},
#endif
62
    {"nofollow", NOFOLLOW_SYMLINKS},
63
    {"nohelp", NO_HELP},
Chris Allegretta's avatar
Chris Allegretta committed
64
#ifndef DISABLE_WRAPPING
65
    {"nowrap", NO_WRAP},
Chris Allegretta's avatar
Chris Allegretta committed
66
#endif
67
#ifndef DISABLE_OPERATINGDIR
68
    {"operatingdir", 0},
69
#endif
70
#ifndef DISABLE_JUSTIFY
71
72
73
74
75
76
77
78
79
    {"quotestr", 0},
#endif
#ifdef HAVE_REGEX_H
    {"regexp", USE_REGEXP},
#endif
#ifndef NANO_SMALL
    {"smooth", SMOOTHSCROLL},
#endif
#ifndef DISABLE_SPELLER
80
    {"speller", 0},
81
82
83
#endif
    {"suspend", SUSPEND},
    {"tabsize", 0},
84
85
    {"tempfile", TEMP_OPT},
    {"view", VIEW_MODE},
86
    {NULL, 0}
87
};
88

89
90
91
92
static int errors = 0;
static int lineno = 0;
static char *nanorc;

93
/* We have an error in some part of the rcfile; put it on stderr and
Chris Allegretta's avatar
Chris Allegretta committed
94
   make the user hit return to continue starting up nano. */
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
95
void rcfile_error(const char *msg, ...)
96
97
98
99
{
    va_list ap;

    fprintf(stderr, "\n");
Chris Allegretta's avatar
Chris Allegretta committed
100
101
102
    if (lineno > 0)
	fprintf(stderr, _("Error in %s on line %d: "), nanorc, lineno);

103
104
105
106
107
    va_start(ap, msg);
    vfprintf(stderr, msg, ap);
    va_end(ap);
    fprintf(stderr, _("\nPress return to continue starting nano\n"));

108
    while (getchar() != '\n');
109
110
}

Chris Allegretta's avatar
Chris Allegretta committed
111
/* Just print the error (one of many, perhaps) but don't abort, yet. */
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
112
void rcfile_msg(const char *msg, ...)
113
114
115
{
    va_list ap;

116
117
    if (!errors) {
	errors = 1;
118
119
120
121
122
123
124
125
	fprintf(stderr, "\n");
    }
    va_start(ap, msg);
    vfprintf(stderr, msg, ap);
    va_end(ap);
    fprintf(stderr, "\n");
}

Chris Allegretta's avatar
Chris Allegretta committed
126
/* Parse the next word from the string.  Returns NULL if we hit EOL. */
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
127
char *parse_next_word(char *ptr)
128
{
129
130
131
132
133
134
135
136
137
    while (*ptr != ' ' && *ptr != '\t' && *ptr != '\n' && *ptr != '\0')
	ptr++;

    if (*ptr == '\0')
	return NULL;

    /* Null terminate and advance ptr */
    *ptr++ = 0;

Chris Allegretta's avatar
Chris Allegretta committed
138
    while (*ptr == ' ' || *ptr == '\t')
139
140
141
142
	ptr++;

    return ptr;
}
143

Chris Allegretta's avatar
Chris Allegretta committed
144
145
146
147
148
149
/* The keywords operatingdir, fill, tabsize, speller, and quotestr take
 * an argument when set.  Among these, operatingdir, speller, and
 * quotestr have to allow tabs and spaces in the argument.  Thus, if the
 * next word starts with a ", we say it ends with the last " of the line.
 * Otherwise, the word is interpreted as usual.  That is so the arguments
 * can contain "s too. */
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
150
151
char *parse_argument(char *ptr)
{
Chris Allegretta's avatar
Chris Allegretta committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    const char *ptr_bak = ptr;
    char *last_quote = NULL;

    assert(ptr != NULL);

    if (*ptr != '"')
	return parse_next_word(ptr);

    do {
	ptr++;
	if (*ptr == '"')
	    last_quote = ptr;
    } while (*ptr != '\n' && *ptr != '\0');

    if (last_quote == NULL) {
	if (*ptr == '\0')
	    ptr = NULL;
	else
	    *ptr++ = '\0';
	rcfile_error(_("argument %s has unterminated \""), ptr_bak);
    } else {
	*last_quote = '\0';
	ptr = last_quote + 1;
    }
    if (ptr != NULL)
	while (*ptr == ' ' || *ptr == '\t')
	    ptr++;
    return ptr;
}

#ifdef ENABLE_COLOR

David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
184
int colortoint(const char *colorname, int *bright)
185
186
187
188
189
190
{
    int mcolor = 0;

    if (colorname == NULL)
	return -1;

Chris Allegretta's avatar
Chris Allegretta committed
191
    if (!strncasecmp(colorname, "bright", 6)) {
192
	*bright = 1;
193
194
	colorname += 6;
    }
195

196
    if (!strcasecmp(colorname, "green"))
Chris Allegretta's avatar
Chris Allegretta committed
197
	mcolor = COLOR_GREEN;
198
    else if (!strcasecmp(colorname, "red"))
Chris Allegretta's avatar
Chris Allegretta committed
199
	mcolor = COLOR_RED;
200
    else if (!strcasecmp(colorname, "blue"))
Chris Allegretta's avatar
Chris Allegretta committed
201
	mcolor = COLOR_BLUE;
202
    else if (!strcasecmp(colorname, "white"))
Chris Allegretta's avatar
Chris Allegretta committed
203
	mcolor = COLOR_WHITE;
204
    else if (!strcasecmp(colorname, "yellow"))
Chris Allegretta's avatar
Chris Allegretta committed
205
	mcolor = COLOR_YELLOW;
206
    else if (!strcasecmp(colorname, "cyan"))
Chris Allegretta's avatar
Chris Allegretta committed
207
	mcolor = COLOR_CYAN;
208
    else if (!strcasecmp(colorname, "magenta"))
Chris Allegretta's avatar
Chris Allegretta committed
209
	mcolor = COLOR_MAGENTA;
210
    else if (!strcasecmp(colorname, "black"))
Chris Allegretta's avatar
Chris Allegretta committed
211
	mcolor = COLOR_BLACK;
212
    else {
213
214
215
216
	rcfile_error(_("color %s not understood.\n"
		       "Valid colors are \"green\", \"red\", \"blue\", \n"
		       "\"white\", \"yellow\", \"cyan\", \"magenta\" and \n"
		       "\"black\", with the optional prefix \"bright\".\n"));
217
218
219
220
221
222
	exit(1);
    }

    return mcolor;
}

223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
char *parse_next_regex(char *ptr)
{
    while ((*ptr != '"' || (*(ptr + 1) != ' ' && *(ptr + 1) != '\n'))
	   && *ptr != '\n' && *ptr != '\0')
	ptr++;

    if (*ptr == '\0')
	return NULL;

    /* Null terminate and advance ptr */
    *ptr++ = '\0';

    while (*ptr == ' ' || *ptr == '\t')
	ptr++;

    return ptr;
}

David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
241
void parse_syntax(char *ptr)
242
243
{
    syntaxtype *tmpsyntax = NULL;
Chris Allegretta's avatar
Chris Allegretta committed
244
    const char *fileregptr = NULL, *nameptr = NULL;
245
246
247
248
249
250
251
252
253
254
    exttype *exttmp = NULL;

    while (*ptr == ' ')
	ptr++;

    if (*ptr == '\n' || *ptr == '\0')
	return;

    if (*ptr != '"') {
	rcfile_error(_("regex strings must begin and end with a \" character\n"));
255
	return;
256
257
258
259
260
261
262
263
    }
    ptr++;

    nameptr = ptr;
    ptr = parse_next_regex(ptr);

    if (ptr == NULL) {
	rcfile_error(_("Missing syntax name"));
264
	return;
265
266
    }

Chris Allegretta's avatar
Chris Allegretta committed
267
268
269
    if (syntaxes == NULL) {
	syntaxes = (syntaxtype *)nmalloc(sizeof(syntaxtype));
	tmpsyntax = syntaxes;
270
	SET(COLOR_SYNTAX);
Chris Allegretta's avatar
Chris Allegretta committed
271
272
273
274
275
276
    } else {
	for (tmpsyntax = syntaxes; tmpsyntax->next != NULL;
		tmpsyntax = tmpsyntax->next)
	    ;
	tmpsyntax->next = (syntaxtype *)nmalloc(sizeof(syntaxtype));
	tmpsyntax = tmpsyntax->next;
277
#ifdef DEBUG
Chris Allegretta's avatar
Chris Allegretta committed
278
	fprintf(stderr, _("Adding new syntax after 1st\n"));
279
#endif
Chris Allegretta's avatar
Chris Allegretta committed
280
281
282
283
284
    }
    tmpsyntax->desc = mallocstrcpy(NULL, nameptr);
    tmpsyntax->color = NULL;
    tmpsyntax->extensions = NULL;
    tmpsyntax->next = NULL;
285
#ifdef DEBUG
Chris Allegretta's avatar
Chris Allegretta committed
286
287
    fprintf(stderr, _("Starting a new syntax type\n"));
    fprintf(stderr, "string val=%s\n", nameptr);
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#endif

    /* Now load in the extensions to their part of the struct */
    while (*ptr != '\n' && *ptr != '\0') {
	while (*ptr != '"' && *ptr != '\n' && *ptr != '\0')
	    ptr++;

	if (*ptr == '\n' || *ptr == '\0')
	    return;
	ptr++;

	fileregptr = ptr;
	ptr = parse_next_regex(ptr);

	if (tmpsyntax->extensions == NULL) {
Chris Allegretta's avatar
Chris Allegretta committed
303
304
305
	    tmpsyntax->extensions = (exttype *)nmalloc(sizeof(exttype));
	    exttmp = tmpsyntax->extensions;
	} else {
306
307
	    for (exttmp = tmpsyntax->extensions; exttmp->next != NULL;
		 exttmp = exttmp->next);
Chris Allegretta's avatar
Chris Allegretta committed
308
309
	    exttmp->next = (exttype *)nmalloc(sizeof(exttype));
	    exttmp = exttmp->next;
310
	}
Chris Allegretta's avatar
Chris Allegretta committed
311
312
	exttmp->val = mallocstrcpy(NULL, fileregptr);
	exttmp->next = NULL;
313
    }
314
315
}

316
/* Parse the color stuff into the colorstrings array */
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
317
void parse_colors(char *ptr)
318
{
319
320
    int fg, bg, bright = 0;
    int expectend = 0;		/* Do we expect an end= line? */
Chris Allegretta's avatar
Chris Allegretta committed
321
    char *fgstr;
322
    colortype *tmpcolor = NULL;
323
    syntaxtype *tmpsyntax = NULL;
324
325
326
327
328

    fgstr = ptr;
    ptr = parse_next_word(ptr);

    if (ptr == NULL) {
329
	rcfile_error(_("Missing color name"));
330
	return;
331
332
333
334
    }

    if (strstr(fgstr, ",")) {
	strtok(fgstr, ",");
Chris Allegretta's avatar
Chris Allegretta committed
335
	bg = colortoint(strtok(NULL, ","), &bright);
336
    } else
Chris Allegretta's avatar
Chris Allegretta committed
337
	bg = -1;
338

339
    fg = colortoint(fgstr, &bright);
340

341
342
    if (syntaxes == NULL) {
	rcfile_error(_("Cannot add a color directive without a syntax line"));
343
	return;
344
345
346
347
348
349
    }

    for (tmpsyntax = syntaxes; tmpsyntax->next != NULL;
	 tmpsyntax = tmpsyntax->next)
	;

350
    /* Now the fun part, start adding regexps to individual strings
351
       in the colorstrings array, woo! */
352

353
354
355
356
357
358
359
360
361
362
363
364
365
366
    while (*ptr != '\0') {
	while (*ptr == ' ')
	    ptr++;

	if (*ptr == '\n' || *ptr == '\0')
	    break;

	if (!strncasecmp(ptr, "start=", 6)) {
	    ptr += 6;
	    expectend = 1;
	}

	if (*ptr != '"') {
	    rcfile_error(_("regex strings must begin and end with a \" character\n"));
367
	    ptr = parse_next_regex(ptr);
368
369
370
	    continue;
	}
	ptr++;
371

372
373
374
	if (tmpsyntax->color == NULL) {
	    tmpsyntax->color = nmalloc(sizeof(colortype));
	    tmpcolor = tmpsyntax->color;
375
#ifdef DEBUG
Chris Allegretta's avatar
Chris Allegretta committed
376
	    fprintf(stderr, _("Starting a new colorstring for fg %d bg %d\n"),
377
		    fg, bg);
378
#endif
379
	} else {
380
	    for (tmpcolor = tmpsyntax->color;
381
		 tmpcolor->next != NULL; tmpcolor = tmpcolor->next);
382
#ifdef DEBUG
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
383
	    fprintf(stderr, _("Adding new entry for fg %d bg %d\n"), fg, bg);
384
#endif
385
386
387
	    tmpcolor->next = nmalloc(sizeof(colortype));
	    tmpcolor = tmpcolor->next;
	}
Chris Allegretta's avatar
Chris Allegretta committed
388
389
390
391
	tmpcolor->fg = fg;
	tmpcolor->bg = bg;
	tmpcolor->bright = bright;
	tmpcolor->next = NULL;
392

Chris Allegretta's avatar
Chris Allegretta committed
393
394
395
396
397
398
399
400
401
402
	tmpcolor->start = ptr;
	ptr = parse_next_regex(ptr);
	tmpcolor->start = mallocstrcpy(NULL, tmpcolor->start);
#ifdef DEBUG
	fprintf(stderr, _("string val=%s\n"), tmpcolor->start);
#endif

	if (!expectend)
	    tmpcolor->end = NULL;
	else {
403
404
	    if (ptr == NULL || strncasecmp(ptr, "end=", 4)) {
		rcfile_error(_
405
			     ("\"start=\" requires a corresponding \"end=\""));
406
407
		return;
	    }
408

409
	    ptr += 4;
410

411
412
413
414
	    if (*ptr != '"') {
		rcfile_error(_
			     ("regex strings must begin and end with a \" character\n"));
		continue;
415
416
417
	    }
	    ptr++;

Chris Allegretta's avatar
Chris Allegretta committed
418
	    tmpcolor->end = ptr;
419
	    ptr = parse_next_regex(ptr);
Chris Allegretta's avatar
Chris Allegretta committed
420
	    tmpcolor->end = mallocstrcpy(NULL, tmpcolor->end);
421
#ifdef DEBUG
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
422
	    fprintf(stderr, _("For end part, beginning = \"%s\"\n"),
Chris Allegretta's avatar
Chris Allegretta committed
423
		    tmpcolor->end);
424
#endif
Chris Allegretta's avatar
Chris Allegretta committed
425
	}
426
    }
427
}
428
429

#endif /* ENABLE_COLOR */
430

431
/* Parse the RC file, once it has been opened successfully */
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
432
void parse_rcfile(FILE *rcstream)
433
434
{
    char *buf, *ptr, *keyword, *option;
435
    int set = 0, i, j;
436

437
    buf = charalloc(1024);
Chris Allegretta's avatar
Chris Allegretta committed
438
    while (fgets(buf, 1023, rcstream) != 0) {
439
440
	lineno++;
	ptr = buf;
Chris Allegretta's avatar
Chris Allegretta committed
441
	while (*ptr == ' ' || *ptr == '\t')
442
443
444
445
446
447
448
449
450
	    ptr++;

	if (*ptr == '\n' || *ptr == '\0')
	    continue;

	if (*ptr == '#') {
#ifdef DEBUG
	    fprintf(stderr, _("parse_rcfile: Read a comment\n"));
#endif
451
	    continue;		/* Skip past commented lines */
452
453
454
455
456
	}

	/* Else skip to the next space */
	keyword = ptr;
	ptr = parse_next_word(ptr);
457
	if (ptr == NULL)
458
459
460
461
462
463
464
	    continue;

	/* Else try to parse the keyword */
	if (!strcasecmp(keyword, "set"))
	    set = 1;
	else if (!strcasecmp(keyword, "unset"))
	    set = -1;
465
#ifdef ENABLE_COLOR
466
	else if (!strcasecmp(keyword, "syntax"))
Chris Allegretta's avatar
Chris Allegretta committed
467
	    parse_syntax(ptr);
468
	else if (!strcasecmp(keyword, "color"))
Chris Allegretta's avatar
Chris Allegretta committed
469
	    parse_colors(ptr);
470
#endif				/* ENABLE_COLOR */
471
	else {
472
	    rcfile_msg(_("command %s not understood"), keyword);
473
474
475
476
477
478
479
480
	    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) {
481
	    for (i = 0; rcopts[i].name != NULL; i++) {
482
		if (!strcasecmp(option, rcopts[i].name)) {
483
#ifdef DEBUG
484
485
		    fprintf(stderr, _("parse_rcfile: Parsing option %s\n"),
			    rcopts[i].name);
486
#endif
487
		    if (set == 1) {
Chris Allegretta's avatar
Chris Allegretta committed
488
489
490
491
			if (!strcasecmp(rcopts[i].name, "tabsize")
#ifndef DISABLE_OPERATINGDIR
				|| !strcasecmp(rcopts[i].name, "operatingdir")
#endif
492
#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta's avatar
Chris Allegretta committed
493
				|| !strcasecmp(rcopts[i].name, "fill")
494
#endif
495
#ifndef DISABLE_JUSTIFY
Chris Allegretta's avatar
Chris Allegretta committed
496
				|| !strcasecmp(rcopts[i].name, "quotestr")
497
#endif
498
#ifndef DISABLE_SPELLER
Chris Allegretta's avatar
Chris Allegretta committed
499
				|| !strcasecmp(rcopts[i].name, "speller")
500
#endif
Chris Allegretta's avatar
Chris Allegretta committed
501
				) {
502
			    if (*ptr == '\n' || *ptr == '\0') {
503
504
505
				rcfile_error(_
					     ("option %s requires an argument"),
					     rcopts[i].name);
506
507
508
				continue;
			    }
			    option = ptr;
Chris Allegretta's avatar
Chris Allegretta committed
509
510
511
512
513
514
515
516
517
518
519
			    if (*option == '"')
				option++;
			    ptr = parse_argument(ptr);
#ifdef DEBUG
			    fprintf(stderr, "option = %s\n", option);
#endif
#ifndef DISABLE_OPERATINGDIR
			    if (!strcasecmp(rcopts[i].name, "operatingdir"))
				operating_dir = mallocstrcpy(NULL, option);
			    else
#endif
520
#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta's avatar
Chris Allegretta committed
521
522
523
524
525
526
527
528
529
			    if (!strcasecmp(rcopts[i].name, "fill")) {
				char *first_error;

				/* Using strtol instead of atoi lets us
				 * accept 0 while checking other
				 * errors. */
				j = (int)strtol(option, &first_error, 10);
				if (errno == ERANGE || *option == '\0' || *first_error != '\0')
				    rcfile_error(_("requested fill size %d invalid"),
530
						 j);
Chris Allegretta's avatar
Chris Allegretta committed
531
532
				else
				    wrap_at = j;
533
			    } else
Chris Allegretta's avatar
Chris Allegretta committed
534
#endif
535
#ifndef DISABLE_JUSTIFY
Chris Allegretta's avatar
Chris Allegretta committed
536
537
538
			    if (!strcasecmp(rcopts[i].name, "quotestr"))
				quotestr = mallocstrcpy(NULL, option);
			    else
539
#endif
540
#ifndef DISABLE_SPELLER
Chris Allegretta's avatar
Chris Allegretta committed
541
542
543
			    if (!strcasecmp(rcopts[i].name, "speller"))
				alt_speller = mallocstrcpy(NULL, option);
			    else
544
#endif
Chris Allegretta's avatar
Chris Allegretta committed
545
546
547
548
549
550
551
552
553
554
555
556
			    {
				char *first_error;

				/* Using strtol instead of atoi lets us
				 * accept 0 while checking other
				 * errors. */
				j = (int)strtol(option, &first_error, 10);
				if (errno == ERANGE || *option == '\0' || *first_error != '\0')
				    rcfile_error(_("requested tab size %d invalid"),
						 j);
				else
				    tabsize = j;
557
			    }
558
			} else
559
560
			    SET(rcopts[i].flag);
#ifdef DEBUG
561
562
			fprintf(stderr, _("set flag %d!\n"),
				rcopts[i].flag);
563
564
565
566
#endif
		    } else {
			UNSET(rcopts[i].flag);
#ifdef DEBUG
567
568
			fprintf(stderr, _("unset flag %d!\n"),
				rcopts[i].flag);
569
#endif
570
		    }
571
572
573
574
		}
	    }
	}
    }
Chris Allegretta's avatar
Chris Allegretta committed
575
    free(buf);
576
577
578
579
580
581
582
583
584
585
    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)
{
    FILE *rcstream;
Chris Allegretta's avatar
Chris Allegretta committed
586
587
    const struct passwd *userage;
    uid_t euid = geteuid();
588

Chris Allegretta's avatar
Chris Allegretta committed
589
590
591
#ifdef SYSCONFDIR
    assert(sizeof(SYSCONFDIR) == strlen(SYSCONFDIR) + 1);
    nanorc = charalloc(sizeof(SYSCONFDIR) + 7);
592
593
    sprintf(nanorc, "%s/nanorc", SYSCONFDIR);
    /* Try to open system nanorc */
Chris Allegretta's avatar
Chris Allegretta committed
594
595
596
597
598
599
    if ((rcstream = fopen(nanorc, "r")) != NULL) {
	/* Parse it! */
	parse_rcfile(rcstream);
	fclose(rcstream);
    }
#endif
600

Chris Allegretta's avatar
Chris Allegretta committed
601
602
603
604
605
    /* Determine home directory using getpwent(), don't rely on $HOME */
    do {
	userage = getpwent();
    } while (userage != NULL && userage->pw_uid != euid);
    endpwent();
606

Chris Allegretta's avatar
Chris Allegretta committed
607
    lineno = 0;
Chris Allegretta's avatar
Chris Allegretta committed
608

609
    if (userage == NULL) {
Chris Allegretta's avatar
Chris Allegretta committed
610
	rcfile_error(_("I can't find my home directory!  Wah!"));
611
612
	SET(NO_RCFILE); /* if no .nanorc, don't try to read .nano_history */
    } else {
Chris Allegretta's avatar
Chris Allegretta committed
613
614
615
	nanorc = nrealloc(nanorc, strlen(userage->pw_dir) + 9);
	sprintf(nanorc, "%s/.nanorc", userage->pw_dir);

616
617
618
619
620
621
#if defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING)
    /* If we've already read $SYSCONFDIR/nanorc (if it's there), we're
       root, and --disable-wrapping-as-root is used, turn wrapping off */
	if (euid == 0)
	    SET(NO_WRAP);
#endif
Chris Allegretta's avatar
Chris Allegretta committed
622
623
	if ((rcstream = fopen(nanorc, "r")) == NULL) {
	    /* Don't complain about the file not existing */
624
	    if (errno != ENOENT) {
Chris Allegretta's avatar
Chris Allegretta committed
625
626
		rcfile_error(_("Unable to open ~/.nanorc file, %s"),
			strerror(errno));
627
628
		SET(NO_RCFILE);
	    }
Chris Allegretta's avatar
Chris Allegretta committed
629
630
631
632
	} else {
	    parse_rcfile(rcstream);
	    fclose(rcstream);
	}
633
634
    }

Chris Allegretta's avatar
Chris Allegretta committed
635
    free(nanorc);
636
637
638
#ifdef ENABLE_COLOR
    set_colorpairs();
#endif
639
640
}

641
#endif /* ENABLE_NANORC */