1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include "conf.h"
7 #include "err.h"
8 #include "mem.h"
9
10
11 /* Allocates memory and loads a file, returns file length
12 */
13
load_file(char * path,void ** mem)14 static int load_file (char *path, void **mem)
15 {
16 int fd, len;
17
18 if ((fd = open (path, O_RDONLY)) == -1)
19 return ERROR;
20
21 len = lseek (fd, 0, SEEK_END);
22 lseek (fd, 0, SEEK_SET);
23
24 mem_resize (mem, len);
25
26 if (read (fd, *mem, len) != len) {
27 free (*mem);
28 *mem = 0;
29 close (fd);
30 return ERROR;
31 }
32 close (fd);
33
34 return len;
35 }
36
37
38 /* Returns ERROR if there are no more lines
39 */
40
next_line(struct CONFIG * cfg)41 static int next_line (struct CONFIG *cfg)
42 {
43 while (cfg->line_pos < cfg->file_len){
44 if (cfg->file[cfg->line_pos] == 10) {
45 cfg->line_pos++;
46 break;
47 }
48 cfg->line_pos++;
49 }
50 if (cfg->line_pos >= cfg->file_len)
51 return ERROR;
52
53 return E_OK;
54 }
55
56
57 /* Returns ERROR if there are no characters on the line
58 */
59
set_line_end(struct CONFIG * cfg)60 static int set_line_end (struct CONFIG *cfg)
61 {
62 char c;
63 int pos = cfg->line_pos;
64
65 while (pos < cfg->file_len) {
66 c = cfg->file[pos];
67 if (c == 10 || c == '#') {
68 pos--;
69 break;
70 }
71 pos++;
72 }
73 if (pos < cfg->line_pos)
74 return ERROR;
75
76 cfg->line_end = pos;
77 return E_OK;
78 }
79
80
81 /* Returns ERROR if there are no more arguments
82 */
83
next_arg(struct CONFIG * cfg)84 static int next_arg (struct CONFIG *cfg)
85 {
86 char c;
87
88 while (cfg->arg_pos <= cfg->line_end) {
89 c = cfg->file[cfg->arg_pos];
90 if (c != 9 && c != 32)
91 break;
92 cfg->arg_pos++;
93 }
94 if (cfg->arg_pos > cfg->line_end)
95 return ERROR;
96
97 return E_OK;
98 }
99
100
101 /* Returns length of argument
102 */
103
get_arg_len(struct CONFIG * cfg)104 static int get_arg_len (struct CONFIG *cfg)
105 {
106 int c, len = 0;
107
108 while (cfg->arg_pos <= cfg->line_end) {
109 c = cfg->file[cfg->arg_pos];
110 if (c == 9 || c == 32)
111 break;
112
113 cfg->arg_pos++;
114 len++;
115 }
116 return len;
117 }
118
119
evaluate(struct CONFIG * cfg)120 static void evaluate (struct CONFIG *cfg)
121 {
122 int arg_pos, arg_len, args, fno = 0, str_len, i;
123 char *s1 = 0, *s2;
124
125 do {
126 if (set_line_end (cfg) == E_OK) {
127 cfg->arg_pos = cfg->line_pos;
128 args = 0;
129 str_len = 0;
130 while (next_arg (cfg) != ERROR) {
131 arg_pos = cfg->arg_pos;
132 arg_len = get_arg_len (cfg);
133
134 if (!args) {
135 fno = cfg->formats;
136 cfg->formats++;
137 mem_resize ((void **)&cfg->format,
138 cfg->formats * sizeof (struct CFG_FORMAT));
139 s1 = cfg->format[fno].strings;
140 }
141
142 str_len += arg_len + 1;
143 if (str_len > CFG_STRLEN) {
144 fprintf (stderr, "error: Arguments in juke.conf longer "
145 "than %d characters\n", CFG_STRLEN);
146 exit (ERROR);
147 }
148
149 s2 = cfg->file + arg_pos;
150 for (i=arg_len; i>0;i--)
151 *s1++ = *s2++;
152 *s1++ = 0;
153
154 args++;
155 if (args > CFG_ARGS) {
156 fprintf (stderr, "error: Arguments in juke.conf more "
157 "than %d\n", CFG_ARGS);
158 exit (ERROR);
159 }
160 }
161 cfg->format[fno].args = args;
162 cfg->format[fno].match_len = strlen (cfg->format[fno].strings);
163 }
164 } while (next_line (cfg) == E_OK);
165 }
166
167
build_arg_lists(struct CONFIG * cfg)168 static void build_arg_lists (struct CONFIG *cfg)
169 {
170 int i, j, pos, len;
171
172 for (i=0;i<cfg->formats;i++) {
173 pos = cfg->format[i].match_len + 1;
174 for (j=0; j<cfg->format[i].args-1; j++) {
175 len = strlen (cfg->format[i].strings + pos);
176 cfg->format[i].arg_list[j] = cfg->format[i].strings + pos;
177 pos += len + 1;
178 }
179 cfg->format[i].arg_list[j+1] = 0;
180 }
181 }
182
183
config_load(struct CONFIG * cfg)184 void config_load (struct CONFIG *cfg)
185 {
186 char *home, config[]="/.juke.conf", *str = 0;
187 int str_len;
188
189 if ((home = getenv ("HOME"))) {
190 str_len = strlen (home) + strlen (config) + 1;
191 mem_resize ((void *)&str, str_len);
192 *str = 0;
193 strcat (str, home);
194 strcat (str, config);
195
196 cfg->file_len = load_file (str, (void **)&cfg->file);
197 free (str);
198
199 if (cfg->file_len != ERROR) {
200 evaluate (cfg);
201 if (! cfg->formats) {
202 fprintf (stderr, "error: No formats in ~/.juke.conf\n");
203 exit (ERROR);
204 }
205 build_arg_lists (cfg);
206 free (cfg->file);
207 return;
208 }
209 }
210 cfg->file_len = load_file (CFG_RCFILE, (void **)&cfg->file);
211 if (cfg->file_len != ERROR) {
212 evaluate (cfg);
213 if (! cfg->formats) {
214 fprintf (stderr, "error: No formats in " CFG_RCFILE "\n");
215 exit (ERROR);
216 }
217 build_arg_lists (cfg);
218 free (cfg->file);
219 } else {
220 fprintf (stderr, "error: Could not find any configuration file\n");
221 exit (ERROR);
222 }
223 }
224