Subversion Repositories SvarDOS

Rev

Rev 219 | Rev 227 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
219 mateuszvis 1
/*
2
 * This file is part of FDNPKG.
3
 *
4
 * Loads the list of repositories from the config file specified in %FDNPKG%.
5
 * Returns the amount of repositories found (and loaded) on success, or -1 on failure.
6
 *
7
 * Copyright (C) 2012-2016 Mateusz Viste
8
 */
9
 
10
#include <stdio.h>  /* printf(), fclose(), fopen()... */
11
#include <string.h> /* strcasecmp() */
12
#include <stdlib.h> /* malloc(), free() */
13
 
14
#include "crc32.h"  /* crc32() */
15
#include "fdnpkg.h" /* PKGINST_NOSOURCE, PKGINST_SKIPLINKS... */
16
#include "helpers.h" /* slash2backslash(), removeDoubleBackslashes()... */
17
#include "kprintf.h"
18
#include "loadconf.h"
19
#include "parsecmd.h"
20
#include "version.h"
21
 
22
 
225 mateuszvis 23
void freeconf(struct customdirs **dirlist) {
219 mateuszvis 24
  struct customdirs *curpos;
25
  /* free the linked list of custom dirs */
26
  while (*dirlist != NULL) {
27
    curpos = *dirlist;
28
    if (curpos->name != NULL) free(curpos->name);
29
    if (curpos->location != NULL) free(curpos->location);
30
    *dirlist = (*dirlist)->next;
31
    free(curpos);
32
  }
33
  *dirlist = NULL;
34
}
35
 
36
 
37
static int checkfordoubledirlist(struct customdirs *dirlist) {
38
  struct customdirs *curpos;
39
  for (; dirlist != NULL; dirlist = dirlist->next) {
40
    for (curpos = dirlist->next; curpos != NULL; curpos = curpos->next) {
41
      if (strcasecmp(curpos->name, dirlist->name) == 0) {
42
        kitten_printf(7, 0, "Error: custom dir '%s' is listed twice!", curpos->name);
43
        puts("");
44
        return(-1);
45
      }
46
    }
47
  }
48
  return(0);
49
}
50
 
51
 
52
/* validates dirlist entries: check that they are absolute paths and are not using restricted names */
53
static int validatedirlist(struct customdirs *dirlist) {
54
  for (; dirlist != NULL; dirlist = dirlist->next) {
55
    /* the location must be at least 3 characters long to be a valid absolute path (like 'c:\')*/
56
    if (strlen(dirlist->location) < 3) {
57
      kitten_printf(7, 15, "Error: custom dir '%s' is not a valid absolute path!", dirlist->name);
58
      puts("");
59
      return(-1);
60
    }
61
    /* is it a valid absolute path? should start with [a..Z]:\ */
62
    if ((dirlist->location[1] != ':') ||
63
       ((dirlist->location[2] != '/') && (dirlist->location[2] != '\\')) ||
64
       (((dirlist->location[0] < 'a') || (dirlist->location[0] > 'z')) && ((dirlist->location[0] < 'A') || (dirlist->location[0] > 'Z')))) {
65
      kitten_printf(7, 15, "Error: custom dir '%s' is not a valid absolute path!", dirlist->name);
66
      puts("");
67
      return(-1);
68
    }
69
    /* check for forbidden names */
70
    if ((strcasecmp(dirlist->name, "appinfo") == 0) ||
71
        (strcasecmp(dirlist->name, "bin") == 0) ||
72
        (strcasecmp(dirlist->name, "doc") == 0) ||
73
        (strcasecmp(dirlist->name, "help") == 0) ||
74
        (strcasecmp(dirlist->name, "nls") == 0) ||
75
        (strcasecmp(dirlist->name, "packages") == 0)) {
76
      kitten_printf(7, 16, "Error: custom dir '%s' is a reserved name!", dirlist->name);
77
      puts("");
78
      return(-1);
79
    }
80
  }
81
  return(0);
82
}
83
 
84
 
85
/* add (and allocates) a new custom dir entry to dirlist. Returns 0 on success,
86
   or non-zero on failure (failures happen on out of memory events). */
87
static int addnewdir(struct customdirs **dirlist, char *name, char *location) {
88
  struct customdirs *newentry;
89
  newentry = malloc(sizeof(struct customdirs));
90
  if (newentry == NULL) return(-1);
91
  newentry->name = malloc(strlen(name) + 1);
92
  if (newentry->name == NULL) {
93
    free(newentry);
94
    return(-1);
95
  }
96
  newentry->location = malloc(strlen(location) + 1);
97
  if (newentry->location == NULL) {
98
    free(newentry->name);
99
    free(newentry);
100
    return(-1);
101
  }
102
  strcpy(newentry->name, name);
103
  strcpy(newentry->location, location);
104
  newentry->next = *dirlist;
105
  *dirlist = newentry;
106
  return(0);
107
}
108
 
109
 
225 mateuszvis 110
int loadconf(char *cfgfile, struct customdirs **dirlist, int *flags) {
219 mateuszvis 111
  int bytebuff, parserstate = 0;
112
  FILE *fd;
113
  #define maxtok 16
114
  char token[maxtok];
115
  #define maxval 1024
116
  char value[maxval];
117
  int curtok = 0, curval = 0, nline = 1;
118
 
119
  fd = fopen(cfgfile, "r");
120
  if (fd == NULL) {
121
    kitten_printf(7, 1, "Error: Could not open config file '%s'!", cfgfile);
122
    puts("");
123
    return(-1);
124
  }
125
 
126
  /* read the config file line by line */
127
  do {
128
    bytebuff = fgetc(fd);
129
    if (bytebuff != '\r') {
130
      switch (parserstate) {
131
        case 0: /* Looking for start of line */
132
          if ((bytebuff == EOF) || (bytebuff == ' ') || (bytebuff == '\t')) break;
133
          if (bytebuff == '\n') {
134
            nline += 1;
135
            break;
136
          }
137
          if (bytebuff == '#') {
138
              parserstate = 9;
139
            } else {
140
              token[0] = bytebuff;
141
              curtok = 1;
142
              parserstate = 1;
143
          }
144
          break;
145
        case 1: /* Looking for token end */
146
          if ((bytebuff == EOF) || (bytebuff == '\n')) {
147
            kitten_printf(7, 2, "Warning: token without value on line #%d", nline);
148
            puts("");
149
            if (bytebuff == '\n') nline += 1;
150
            parserstate = 0;
151
            break;
152
          }
153
          if ((bytebuff == ' ') || (bytebuff == '\t')) {
154
              token[curtok] = 0;
155
              parserstate = 2;
156
            } else {
157
              token[curtok] = bytebuff;
158
              curtok += 1;
159
              if (curtok >= maxtok) {
160
                parserstate = 9; /* ignore the line */
161
                kitten_printf(7, 3, "Warning: Config file token overflow on line #%d", nline);
162
                puts("");
163
              }
164
          }
165
          break;
166
        case 2: /* Looking for value start */
167
          if ((bytebuff == EOF) || (bytebuff == '\n')) {
168
            kitten_printf(7, 4, "Warning: token with empty value on line #%d", nline);
169
            puts("");
170
            if (bytebuff == '\n') nline += 1;
171
            parserstate = 0;
172
            break;
173
          }
174
          if ((bytebuff != ' ') && (bytebuff != '\t')) {
175
            value[0] = bytebuff;
176
            curval = 1;
177
            parserstate = 3;
178
          }
179
          break;
180
        case 3: /* Looking for value end */
181
          if ((bytebuff == EOF) || (bytebuff == '\n')) {
182
              parserstate = 0;
183
              value[curval] = 0;
184
              if ((value[curval - 1] == ' ') || (value[curval - 1] == '\t')) {
185
                kitten_printf(7, 5, "Warning: trailing white-space(s) after value on line #%d", nline);
186
                puts("");
187
                while ((value[curval - 1] == ' ') || (value[curval - 1] == '\t')) value[--curval] = 0;
188
              }
189
              /* Interpret the token/value pair now! */
190
              /* printf("token='%s' ; value = '%s'\n", token, value); */
225 mateuszvis 191
              if (strcasecmp(token, "SKIPLINKS") == 0) {
219 mateuszvis 192
                  int tmpint = atoi(value); /* must be 0/1 */
193
                  if (tmpint == 0) {
194
                    /* do nothing */
195
                  } else if (tmpint == 1) {
196
                    *flags |= PKGINST_SKIPLINKS;
197
                  } else {
198
                    kitten_printf(7, 10, "Warning: Ignored an illegal '%s' value at line #%d", "skiplinks", nline);
199
                    puts("");
200
                  }
201
                } else if (strcasecmp(token, "DIR") == 0) { /* custom repository entry */
202
                  char *argv[2], *evar, *evar_content, *realLocation;
203
                  #define realLocation_len 512
204
                  int x, y;
205
                  if (parsecmd(value, argv, 2) != 2) {
206
                    kitten_printf(7, 11, "Warning: Invalid 'DIR' directive found at line #%d", nline);
207
                    puts("");
208
                  }
209
                  realLocation = malloc(realLocation_len);
210
                  if (realLocation == NULL) {
211
                    kitten_printf(2, 14, "Out of memory! (%s)", "malloc realLocation");
212
                    puts("");
225 mateuszvis 213
                    freeconf(dirlist);
219 mateuszvis 214
                    fclose(fd);
215
                    return(-1);
216
                  }
217
                  realLocation[0] = 0; /* force it to be empty, since we might use strcat() on this later! */
218
                  /* resolve possible env variables */
219
                  evar = NULL;
220
                  y = 0;
221
                  for (x = 0; argv[1][x] != 0; x++) {
222
                    if (evar == NULL) { /* searching for % and copying */
223
                        if (argv[1][x] == '%') {
224
                            evar = &argv[1][x+1];
225
                          } else {
226
                            if (y + 1 > realLocation_len) {
227
                              kitten_printf(7, 12, "Error: DIR path too long at line #%d", nline);
228
                              puts("");
225 mateuszvis 229
                              freeconf(dirlist);
219 mateuszvis 230
                              free(realLocation);
231
                              fclose(fd);
232
                              return(-1);
233
                            }
234
                            realLocation[y] = argv[1][x]; /* copy over */
235
                            y++;
236
                            realLocation[y] = 0; /* make sure to terminate the string at any time */
237
                        }
238
                      } else { /* reading a % variable */
239
                        if (argv[1][x] == '%') {
240
                          argv[1][x] = 0;
241
                          evar_content = getenv(evar);
242
                          if (evar_content == NULL) {
243
                            kitten_printf(7, 13, "Error: Found inexisting environnement variable '%s' at line #%d", evar, nline);
244
                            puts("");
225 mateuszvis 245
                            freeconf(dirlist);
219 mateuszvis 246
                            free(realLocation);
247
                            fclose(fd);
248
                            return(-1);
249
                          }
250
                          if (strlen(evar_content) + y + 1 > realLocation_len) {
251
                            kitten_printf(7, 12, "Error: DIR path too long at line #%d", nline);
252
                            puts("");
225 mateuszvis 253
                            freeconf(dirlist);
219 mateuszvis 254
                            free(realLocation);
255
                            fclose(fd);
256
                            return(-1);
257
                          }
258
                          strcat(realLocation, evar_content);
259
                          y += strlen(evar_content);
260
                          evar = NULL;
261
                        }
262
                    }
263
                  }
264
                  /* add the entry to the list */
265
                  slash2backslash(realLocation);
266
                  removeDoubleBackslashes(realLocation);
267
                  if (realLocation[strlen(realLocation) - 1] != '\\') strcat(realLocation, "\\"); /* make sure to end dirs with a backslash */
268
                  if (addnewdir(dirlist, argv[0], realLocation) != 0) {
269
                    kitten_printf(2, 14, "Out of memory! (%s)", "addnewdir");
270
                    puts("");
225 mateuszvis 271
                    freeconf(dirlist);
219 mateuszvis 272
                    free(realLocation);
273
                    fclose(fd);
274
                    return(-1);
275
                  }
276
                  free(realLocation);
277
                } else { /* unknown token */
278
                  kitten_printf(7, 8, "Warning: Unknown token '%s' at line #%d", token, nline);
279
                  puts("");
280
              }
281
              /* interpretation done */
282
              if (bytebuff == '\n') nline += 1;
283
            } else {
284
              value[curval] = bytebuff;
285
              curval += 1;
286
              if ((curval + 1) >= maxval) {
287
                parserstate = 9; /* ignore the line */
288
                kitten_printf(7, 9, "Warning: Config file value overflow on line #%d", nline);
289
                puts("");
290
              }
291
          }
292
          break;
293
        case 9: /* Got comment, ignoring the rest of line */
294
          if (bytebuff == EOF) break;
295
          if (bytebuff == '\n') {
296
            nline += 1;
297
            parserstate = 0;
298
          }
299
          break;
300
      }
301
    }
302
  } while (bytebuff != EOF);
303
  fclose(fd);
304
 
225 mateuszvis 305
  /* perform some validations */
219 mateuszvis 306
  if (checkfordoubledirlist(*dirlist) != 0) return(-1);
307
  if (validatedirlist(*dirlist) != 0) return(-1);
308
 
225 mateuszvis 309
  return(0);
219 mateuszvis 310
}