rcfile.c 15.3 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
53
    {"keypad", ALT_KEYPAD},
#ifndef DISABLE_MOUSE
54
    {"mouse", USE_MOUSE},
55
56
57
58
59
60
61
62
63
#endif
#ifdef ENABLE_MULTIBUFFER
    {"multibuffer", MULTIBUFFER},
#endif
#ifndef NANO_SMALL
    {"noconvert", NO_CONVERT},
#endif
    {"nofollow", FOLLOW_SYMLINKS},
    {"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
    {"pico", PICO_MODE},
71
72
73
74
75
76
77
78
79
80
#ifndef NANO_SMALL
    {"quotestr", 0},
#endif
#ifdef HAVE_REGEX_H
    {"regexp", USE_REGEXP},
#endif
#ifndef NANO_SMALL
    {"smooth", SMOOTHSCROLL},
#endif
#ifndef DISABLE_SPELLER
81
    {"speller", 0},
82
83
84
#endif
    {"suspend", SUSPEND},
    {"tabsize", 0},
85
86
    {"tempfile", TEMP_OPT},
    {"view", VIEW_MODE},
87
    {NULL, 0}
88
};
89

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

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

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

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

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

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

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

Chris Allegretta's avatar
Chris Allegretta committed
127
/* Parse the next word from the string.  Returns NULL if we hit EOL. */
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
128
char *parse_next_word(char *ptr)
129
{
130
131
132
133
134
135
136
137
138
    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
139
    while (*ptr == ' ' || *ptr == '\t')
140
141
142
143
	ptr++;

    return ptr;
}
144

Chris Allegretta's avatar
Chris Allegretta committed
145
146
147
148
149
150
/* 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
151
152
char *parse_argument(char *ptr)
{
Chris Allegretta's avatar
Chris Allegretta committed
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
184
    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
185
int colortoint(const char *colorname, int *bright)
186
187
188
189
190
191
{
    int mcolor = 0;

    if (colorname == NULL)
	return -1;

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

197
    if (!strcasecmp(colorname, "green"))
Chris Allegretta's avatar
Chris Allegretta committed
198
	mcolor = COLOR_GREEN;
199
    else if (!strcasecmp(colorname, "red"))
Chris Allegretta's avatar
Chris Allegretta committed
200
	mcolor = COLOR_RED;
201
    else if (!strcasecmp(colorname, "blue"))
Chris Allegretta's avatar
Chris Allegretta committed
202
	mcolor = COLOR_BLUE;
203
    else if (!strcasecmp(colorname, "white"))
Chris Allegretta's avatar
Chris Allegretta committed
204
	mcolor = COLOR_WHITE;
205
    else if (!strcasecmp(colorname, "yellow"))
Chris Allegretta's avatar
Chris Allegretta committed
206
	mcolor = COLOR_YELLOW;
207
    else if (!strcasecmp(colorname, "cyan"))
Chris Allegretta's avatar
Chris Allegretta committed
208
	mcolor = COLOR_CYAN;
209
    else if (!strcasecmp(colorname, "magenta"))
Chris Allegretta's avatar
Chris Allegretta committed
210
	mcolor = COLOR_MAGENTA;
211
    else if (!strcasecmp(colorname, "black"))
Chris Allegretta's avatar
Chris Allegretta committed
212
	mcolor = COLOR_BLACK;
213
    else {
214
215
216
217
	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"));
218
219
220
221
222
223
	exit(1);
    }

    return mcolor;
}

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
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
242
void parse_syntax(char *ptr)
243
244
{
    syntaxtype *tmpsyntax = NULL;
Chris Allegretta's avatar
Chris Allegretta committed
245
    const char *fileregptr = NULL, *nameptr = NULL;
246
247
248
249
250
251
252
253
254
255
    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"));
256
	return;
257
258
259
260
261
262
263
264
    }
    ptr++;

    nameptr = ptr;
    ptr = parse_next_regex(ptr);

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

Chris Allegretta's avatar
Chris Allegretta committed
268
269
270
    if (syntaxes == NULL) {
	syntaxes = (syntaxtype *)nmalloc(sizeof(syntaxtype));
	tmpsyntax = syntaxes;
271
	SET(COLOR_SYNTAX);
Chris Allegretta's avatar
Chris Allegretta committed
272
273
274
275
276
277
    } else {
	for (tmpsyntax = syntaxes; tmpsyntax->next != NULL;
		tmpsyntax = tmpsyntax->next)
	    ;
	tmpsyntax->next = (syntaxtype *)nmalloc(sizeof(syntaxtype));
	tmpsyntax = tmpsyntax->next;
278
#ifdef DEBUG
Chris Allegretta's avatar
Chris Allegretta committed
279
	fprintf(stderr, _("Adding new syntax after 1st\n"));
280
#endif
Chris Allegretta's avatar
Chris Allegretta committed
281
282
283
284
285
    }
    tmpsyntax->desc = mallocstrcpy(NULL, nameptr);
    tmpsyntax->color = NULL;
    tmpsyntax->extensions = NULL;
    tmpsyntax->next = NULL;
286
#ifdef DEBUG
Chris Allegretta's avatar
Chris Allegretta committed
287
288
    fprintf(stderr, _("Starting a new syntax type\n"));
    fprintf(stderr, "string val=%s\n", nameptr);
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#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
304
305
306
	    tmpsyntax->extensions = (exttype *)nmalloc(sizeof(exttype));
	    exttmp = tmpsyntax->extensions;
	} else {
307
308
	    for (exttmp = tmpsyntax->extensions; exttmp->next != NULL;
		 exttmp = exttmp->next);
Chris Allegretta's avatar
Chris Allegretta committed
309
310
	    exttmp->next = (exttype *)nmalloc(sizeof(exttype));
	    exttmp = exttmp->next;
311
	}
Chris Allegretta's avatar
Chris Allegretta committed
312
313
	exttmp->val = mallocstrcpy(NULL, fileregptr);
	exttmp->next = NULL;
314
    }
315
316
}

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

    fgstr = ptr;
    ptr = parse_next_word(ptr);

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

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

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

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

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

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

354
355
356
357
358
359
360
361
362
363
364
365
366
367
    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"));
368
	    ptr = parse_next_regex(ptr);
369
370
371
	    continue;
	}
	ptr++;
372

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

Chris Allegretta's avatar
Chris Allegretta committed
394
395
396
397
398
399
400
401
402
403
	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 {
404
405
406
407
408
	    if (ptr == NULL || strncasecmp(ptr, "end=", 4)) {
		rcfile_error(_
			     ("\n\t\"start=\" requires a corresponding \"end=\""));
		return;
	    }
409

410
	    ptr += 4;
411

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

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

#endif /* ENABLE_COLOR */
431

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

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

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

	if (*ptr == '#') {
#ifdef DEBUG
	    fprintf(stderr, _("parse_rcfile: Read a comment\n"));
#endif
452
	    continue;		/* Skip past commented lines */
453
454
455
456
457
458
459
460
461
462
463
464
465
	}

	/* 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;
466
#ifdef ENABLE_COLOR
467
	else if (!strcasecmp(keyword, "syntax"))
Chris Allegretta's avatar
Chris Allegretta committed
468
	    parse_syntax(ptr);
469
	else if (!strcasecmp(keyword, "color"))
Chris Allegretta's avatar
Chris Allegretta committed
470
	    parse_colors(ptr);
471
#endif				/* ENABLE_COLOR */
472
	else {
473
	    rcfile_msg(_("command %s not understood"), keyword);
474
475
476
477
478
479
480
481
	    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) {
482
	    for (i = 0; rcopts[i].name != NULL; i++) {
483
		if (!strcasecmp(option, rcopts[i].name)) {
484
#ifdef DEBUG
485
486
		    fprintf(stderr, _("parse_rcfile: Parsing option %s\n"),
			    rcopts[i].name);
487
488
#endif
		    if (set == 1 || rcopts[i].flag == FOLLOW_SYMLINKS) {
Chris Allegretta's avatar
Chris Allegretta committed
489
490
491
492
			if (!strcasecmp(rcopts[i].name, "tabsize")
#ifndef DISABLE_OPERATINGDIR
				|| !strcasecmp(rcopts[i].name, "operatingdir")
#endif
493
#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta's avatar
Chris Allegretta committed
494
				|| !strcasecmp(rcopts[i].name, "fill")
495
#endif
496
#ifndef DISABLE_JUSTIFY
Chris Allegretta's avatar
Chris Allegretta committed
497
				|| !strcasecmp(rcopts[i].name, "quotestr")
498
#endif
499
#ifndef DISABLE_SPELLER
Chris Allegretta's avatar
Chris Allegretta committed
500
				|| !strcasecmp(rcopts[i].name, "speller")
501
#endif
Chris Allegretta's avatar
Chris Allegretta committed
502
				) {
503
			    if (*ptr == '\n' || *ptr == '\0') {
504
505
506
				rcfile_error(_
					     ("option %s requires an argument"),
					     rcopts[i].name);
507
508
509
				continue;
			    }
			    option = ptr;
Chris Allegretta's avatar
Chris Allegretta committed
510
511
512
513
514
515
516
517
518
519
520
			    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
521
#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta's avatar
Chris Allegretta committed
522
523
524
525
526
527
528
529
530
			    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"),
531
						 j);
Chris Allegretta's avatar
Chris Allegretta committed
532
533
				else
				    wrap_at = j;
534
			    } else
Chris Allegretta's avatar
Chris Allegretta committed
535
#endif
536
#ifndef DISABLE_JUSTIFY
Chris Allegretta's avatar
Chris Allegretta committed
537
538
539
			    if (!strcasecmp(rcopts[i].name, "quotestr"))
				quotestr = mallocstrcpy(NULL, option);
			    else
540
#endif
541
#ifndef DISABLE_SPELLER
Chris Allegretta's avatar
Chris Allegretta committed
542
543
544
			    if (!strcasecmp(rcopts[i].name, "speller"))
				alt_speller = mallocstrcpy(NULL, option);
			    else
545
#endif
Chris Allegretta's avatar
Chris Allegretta committed
546
547
548
549
550
551
552
553
554
555
556
557
			    {
				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;
558
			    }
559
			} else
560
561
			    SET(rcopts[i].flag);
#ifdef DEBUG
562
563
			fprintf(stderr, _("set flag %d!\n"),
				rcopts[i].flag);
564
565
566
567
#endif
		    } else {
			UNSET(rcopts[i].flag);
#ifdef DEBUG
568
569
			fprintf(stderr, _("unset flag %d!\n"),
				rcopts[i].flag);
570
#endif
571
		    }
572
573
574
575
		}
	    }
	}
    }
Chris Allegretta's avatar
Chris Allegretta committed
576
    free(buf);
577
578
579
580
581
582
583
584
585
586
    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
587
588
    const struct passwd *userage;
    uid_t euid = geteuid();
589

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

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

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

Chris Allegretta's avatar
Chris Allegretta committed
610
    if (userage == NULL)
Chris Allegretta's avatar
Chris Allegretta committed
611
	rcfile_error(_("I can't find my home directory!  Wah!"));
Chris Allegretta's avatar
Chris Allegretta committed
612
613
614
615
616
617
618
619
620
621
622
623
624
    else {
	nanorc = nrealloc(nanorc, strlen(userage->pw_dir) + 9);
	sprintf(nanorc, "%s/.nanorc", userage->pw_dir);

	if ((rcstream = fopen(nanorc, "r")) == NULL) {
	    /* Don't complain about the file not existing */
	    if (errno != ENOENT)
		rcfile_error(_("Unable to open ~/.nanorc file, %s"),
			strerror(errno));
	} else {
	    parse_rcfile(rcstream);
	    fclose(rcstream);
	}
625
626
    }

Chris Allegretta's avatar
Chris Allegretta committed
627
    free(nanorc);
628
629
630
#ifdef ENABLE_COLOR
    set_colorpairs();
#endif
631
632
}

633
#endif /* ENABLE_NANORC */