1 /* $Id: rcfile.c,v 1.29 2003-02-07 19:44:30 bjk Exp $ */
3 Copyright (C) 2002-2003 Ben Kibbey <bjk@arbornet.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sys/types.h>
35 static int attributes(const char *filename
, int line
, char *str
)
40 while ((tmp
= strsep(&str
, ",")) != NULL
) {
41 if (strcasecmp(tmp
, "BOLD") == 0)
43 else if (strcasecmp(tmp
, "REVERSE") == 0)
45 else if (strcasecmp(tmp
, "NONE") == 0)
47 else if (strcasecmp(tmp
, "DIM") == 0)
49 else if (strcasecmp(tmp
, "STANDOUT") == 0)
51 else if (strcasecmp(tmp
, "UNDERLINE") == 0)
53 else if (strcasecmp(tmp
, "BLINK") == 0)
55 else if (strcasecmp(tmp
, "INVISIBLE") == 0)
58 errx(EXIT_FAILURE
, "%s(%i): invalid attribute \"%s\"", filename
,
65 static short color_name(const char *filename
, int line
, const char *color
)
67 if (strcasecmp(color
, "BLACK") == 0)
69 else if (strcasecmp(color
, "WHITE") == 0)
71 else if (strcasecmp(color
, "GREEN") == 0)
73 else if (strcasecmp(color
, "YELLOW") == 0)
75 else if (strcasecmp(color
, "MAGENTA") == 0)
77 else if (strcasecmp(color
, "BLUE") == 0)
79 else if (strcasecmp(color
, "RED") == 0)
81 else if (strcasecmp(color
, "CYAN") == 0)
84 errx(EXIT_FAILURE
, "%s(%i): invalid color \"%s\"", filename
, line
,
90 static void parse_color(const char *filename
, int line
, const char *str
,
93 char fg
[16], bg
[16], attr
[64], nattr
[64];
94 struct colors ctmp
= *c
;
97 if ((n
= sscanf(str
, "%[a-zA-Z] %[a-zA-Z] %[a-zA-Z,] %[a-zA-Z,]", fg
, bg
,
99 errx(EXIT_FAILURE
, "%s(%i): parse error", filename
, line
);
101 ctmp
.fg
= color_name(filename
, line
, fg
);
102 ctmp
.bg
= color_name(filename
, line
, bg
);
103 ctmp
.attrs
= ctmp
.nattrs
= 0;
106 ctmp
.attrs
= attributes(filename
, line
, attr
);
109 ctmp
.nattrs
= attributes(filename
, line
, nattr
);
115 static int on_or_off(const char *filename
, int lines
, const char *str
)
117 if (strcmp(str
, "on") == 0)
120 if (strcmp(str
, "off") == 0)
123 errx(EXIT_FAILURE
, "%s(%i): invalid value \"%s\"", filename
, lines
, str
);
126 void copydatafile(const char *dst
, const char *src
)
129 char buf
[LINE_MAX
], *s
;
131 snprintf(buf
, sizeof(buf
), "%s/%s", DATA_PATH
, src
);
133 fprintf(stderr
, "%s %s...\n", COPY_DATAFILE
, buf
);
135 if ((fp
= fopen(buf
, "r")) == NULL
) {
140 if ((ofp
= fopen(dst
, "w+")) == NULL
) {
146 while ((s
= fgets(buf
, sizeof(buf
), fp
)) != NULL
)
147 fprintf(ofp
, "%s", s
);
158 status
.mode
= MODE_PLAY
;
161 fancy_results
[0].pgn
= "1-0";
162 fancy_results
[1].pgn
= "0-1";
163 fancy_results
[2].pgn
= "1/2-1/2";
164 fancy_results
[3].pgn
= "*";
165 fancy_results
[0].fancy
= TAG_RESULT_FANCY_WHITE
;
166 fancy_results
[1].fancy
= TAG_RESULT_FANCY_BLACK
;
167 fancy_results
[2].fancy
= TAG_RESULT_FANCY_DRAW
;
168 fancy_results
[3].fancy
= TAG_RESULT_FANCY_NA
;
170 status
.engine
= ENGINE_OFFLINE
;
172 config
.engine
= (DEFAULT_ENGINE
>= MAX_ENGINES
) ? GNUCHESS
: DEFAULT_ENGINE
;
173 config
.engine_cmd
= enginecmd
[config
.engine
];
174 config
.jumpcount
= 5;
176 config
.book_method
= (config
.engine
== GNUCHESS
) ? BOOK_RANDOM
: BOOK_OFF
;
177 config
.engine_depth
= 0;
178 config
.historyagony
= 0;
180 config
.linegraphics
= 0;
181 config
.saveprompt
= 1;
182 config
.deleteprompt
= 1;
183 config
.validmoves
= 1;
184 strncpy(config
.ics_server
, DEFAULT_ICS_SERVER
, sizeof(config
.ics_server
));
185 config
.ics_port
= DEFAULT_ICS_PORT
;
186 config
.ics_user
= DEFAULT_ICS_USER
;
188 set_default_colors();
190 if (stat(config
.nagfile
, &st
) == -1) {
192 copydatafile(config
.nagfile
, "nag.data");
194 warn("%s", config
.nagfile
);
197 if (stat(config
.agonyfile
, &st
) == -1) {
199 copydatafile(config
.agonyfile
, "agony.data");
201 warn("%s", config
.agonyfile
);
204 if (stat(config
.ccfile
, &st
) == -1) {
206 copydatafile(config
.nagfile
, "cc.data");
208 warn("%s", config
.ccfile
);
214 void parse_rcfile(const char *filename
)
217 char *line
, buf
[LINE_MAX
];
219 char *altengine
= NULL
;
221 if ((fp
= fopen(filename
, "r")) == NULL
)
222 err(EXIT_FAILURE
, "%s", filename
);
224 while ((line
= fgets(buf
, sizeof(buf
), fp
)) != NULL
) {
226 char var
[30], val
[50];
227 char token
[MAX_PGN_LINE_LEN
+ 1], value
[MAX_PGN_LINE_LEN
+ 1];
232 if (!line
[0] || line
[0] == '#')
235 if ((n
= sscanf(line
, "%s %[^\n]", var
, val
)) != 2)
236 errx(EXIT_FAILURE
, "%s(%i): parse error %i", filename
, lines
,n
);
238 strncpy(val
, trim(val
), sizeof(val
));
239 strncpy(var
, trim(var
), sizeof(var
));
241 if (strcmp(var
, "book") == 0) {
242 if (strcmp(val
, "prefer") == 0)
243 config
.book_method
= BOOK_PREFER
;
244 else if (strcmp(val
, "random") == 0)
245 config
.book_method
= BOOK_RANDOM
;
246 else if (strcmp(val
, "worst") == 0)
247 config
.book_method
= BOOK_WORST
;
248 else if (strcmp(val
, "best") == 0)
249 config
.book_method
= BOOK_BEST
;
250 else if (strcmp(val
, "off") == 0)
251 config
.book_method
= BOOK_OFF
;
253 errx(EXIT_FAILURE
, "%s(%i): invalid book method \"%s\"",
254 filename
, lines
, val
);
256 else if (strcmp(var
, "jumpcount") == 0) {
258 errx(EXIT_FAILURE
, "%s(%i): value is not an integer", filename
,
261 config
.jumpcount
= atoi(val
);
263 else if (strcmp(var
, "depth") == 0) {
265 errx(EXIT_FAILURE
, "%s(%i): value is not an integer", filename
,
268 config
.engine_depth
= atoi(val
);
270 else if (strcmp(var
, "historyagony") == 0)
271 config
.historyagony
= on_or_off(filename
, lines
, val
);
272 else if (strcmp(var
, "agony") == 0)
273 config
.agony
= on_or_off(filename
, lines
, val
);
274 else if (strcmp(var
, "pgntag") == 0) {
275 if ((n
= sscanf(val
, "%s %s ", token
, value
)) < 1 ||
277 errx(EXIT_FAILURE
, "%s(%i): invalid value \"%s\"", filename
,
283 for (n
= 0; n
< strlen(token
); n
++) {
284 if (!isalnum(token
[n
]) && token
[n
] != '_')
286 "%s(%i): token names must match 0-9A-Za-z_.",
290 token
[0] = toupper(token
[0]);
291 add_tag(&config
.tag
, &config
.tindex
, token
, value
);
293 else if (strcmp(var
, "board_window") == 0)
294 parse_color(filename
, lines
, val
, &config
.color
[CONF_BDWINDOW
]);
295 else if (strcmp(var
, "board_selected") == 0)
296 parse_color(filename
, lines
, val
, &config
.color
[CONF_BSELECTED
]);
297 else if (strcmp(var
, "board_white_moves") == 0)
298 parse_color(filename
, lines
, val
, &config
.color
[CONF_BMOVESW
]);
299 else if (strcmp(var
, "board_black_moves") == 0)
300 parse_color(filename
, lines
, val
, &config
.color
[CONF_BMOVESB
]);
301 else if (strcmp(var
, "board_count") == 0)
302 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCOUNT
]);
303 else if (strcmp(var
, "board_cursor") == 0)
304 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCURSOR
]);
305 else if (strcmp(var
, "board_black") == 0)
306 parse_color(filename
, lines
, val
, &config
.color
[CONF_BBLACK
]);
307 else if (strcmp(var
, "board_white") == 0)
308 parse_color(filename
, lines
, val
, &config
.color
[CONF_BWHITE
]);
309 else if (strcmp(var
, "board_graphics") == 0)
310 parse_color(filename
, lines
, val
, &config
.color
[CONF_BGRAPHICS
]);
311 else if (strcmp(var
, "board_coords") == 0)
312 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCOORDS
]);
313 else if (strcmp(var
, "status_window") == 0)
314 parse_color(filename
, lines
, val
, &config
.color
[CONF_SWINDOW
]);
315 else if (strcmp(var
, "status_title") == 0)
316 parse_color(filename
, lines
, val
, &config
.color
[CONF_STITLE
]);
317 else if (strcmp(var
, "status_border") == 0)
318 parse_color(filename
, lines
, val
, &config
.color
[CONF_SBORDER
]);
319 else if (strcmp(var
, "status_notify") == 0)
320 parse_color(filename
, lines
, val
, &config
.color
[CONF_SNOTIFY
]);
321 else if (strcmp(var
, "status_engine") == 0)
322 parse_color(filename
, lines
, val
, &config
.color
[CONF_SENGINE
]);
323 else if (strcmp(var
, "tag_window") == 0)
324 parse_color(filename
, lines
, val
, &config
.color
[CONF_TWINDOW
]);
325 else if (strcmp(var
, "tag_title") == 0)
326 parse_color(filename
, lines
, val
, &config
.color
[CONF_TTITLE
]);
327 else if (strcmp(var
, "tag_border") == 0)
328 parse_color(filename
, lines
, val
, &config
.color
[CONF_TBORDER
]);
329 else if (strcmp(var
, "history_window") == 0)
330 parse_color(filename
, lines
, val
, &config
.color
[CONF_HWINDOW
]);
331 else if (strcmp(var
, "history_title") == 0)
332 parse_color(filename
, lines
, val
, &config
.color
[CONF_HTITLE
]);
333 else if (strcmp(var
, "history_border") == 0)
334 parse_color(filename
, lines
, val
, &config
.color
[CONF_HBORDER
]);
335 else if (strcmp(var
, "message_window") == 0)
336 parse_color(filename
, lines
, val
, &config
.color
[CONF_MWINDOW
]);
337 else if (strcmp(var
, "message_title") == 0)
338 parse_color(filename
, lines
, val
, &config
.color
[CONF_MTITLE
]);
339 else if (strcmp(var
, "message_border") == 0)
340 parse_color(filename
, lines
, val
, &config
.color
[CONF_MBORDER
]);
341 else if (strcmp(var
, "message_prompt") == 0)
342 parse_color(filename
, lines
, val
, &config
.color
[CONF_MPROMPT
]);
343 else if (strcmp(var
, "input_window") == 0)
344 parse_color(filename
, lines
, val
, &config
.color
[CONF_IWINDOW
]);
345 else if (strcmp(var
, "input_title") == 0)
346 parse_color(filename
, lines
, val
, &config
.color
[CONF_ITITLE
]);
347 else if (strcmp(var
, "input_border") == 0)
348 parse_color(filename
, lines
, val
, &config
.color
[CONF_IBORDER
]);
349 else if (strcmp(var
, "input_prompt") == 0)
350 parse_color(filename
, lines
, val
, &config
.color
[CONF_IPROMPT
]);
351 else if (strcmp(var
, "save_directory") == 0)
352 config
.savedirectory
= strdup(tilde_expand(val
));
353 else if (strcmp(var
, "line_graphics") == 0)
354 config
.linegraphics
= on_or_off(filename
, lines
, val
);
355 else if (strcmp(var
, "save_prompt") == 0)
356 config
.saveprompt
= on_or_off(filename
, lines
, val
);
357 else if (strcmp(var
, "delete_prompt") == 0)
358 config
.deleteprompt
= on_or_off(filename
, lines
, val
);
359 else if (strcmp(var
, "valid_moves") == 0)
360 config
.validmoves
= on_or_off(filename
, lines
, val
);
361 else if (strcmp(var
, "clevel") == 0) {
363 errx(EXIT_FAILURE
, "%s(%i): value is not an integer", filename
,
366 if ((config
.clevel
= atoi(val
)) > 9 || config
.clevel
< 1)
367 errx(EXIT_FAILURE
, "%s(%i): value must be between 1 and 9",
370 else if (strcmp(var
, "ics_server") == 0)
371 strncpy(config
.ics_server
, val
, sizeof(config
.ics_server
));
372 else if (strcmp(var
, "ics_port") == 0) {
374 errx(EXIT_FAILURE
, "%s(%i): value is not an integer", filename
,
377 config
.ics_port
= atoi(val
);
379 else if (strcmp(var
, "ics_user") == 0)
380 config
.ics_user
= strdup(val
);
381 else if (strcmp(var
, "ics_passwd") == 0)
382 config
.ics_passwd
= strdup(val
);
383 else if (strcmp(var
, "engine_cmd") == 0)
384 altengine
= strdup(val
);
385 else if (strcmp(var
, "engine") == 0) {
388 config
.engine_cmd
= enginecmd
[GNUCHESS
];
389 config
.engine
= GNUCHESS
;
392 config
.engine_cmd
= enginecmd
[CRAFTY
];
393 config
.engine
= CRAFTY
;
397 "%s(%i): engine must be 0 through %i", filename
,
398 lines
, MAX_ENGINES
- 1);
402 errx(EXIT_FAILURE
, "%s(%i): invalid parameter \"%s\"", filename
,
409 config
.engine_cmd
= altengine
;