Ejemplo n.º 1
0
/* return zero on success */
int path_join(const char *base, int base_len, const char *extend, int extend_len, char *output, int size)
{
	int i;
	if(extend_len < 0)
		extend_len = strlen(extend);
	
	if(path_isabs(extend))
	{
		/* just copy the extend path */
		if(extend_len+1 > size)
		{
			fprintf(stderr, "'%s' + '%s' results in a too long path\n", base, extend);
			return __LINE__;
		}
		
		memcpy(output, extend, extend_len+1);
		path_normalize(output);
		return 0;
	}
	
	if(base_len < 0)
		base_len = strlen(base);
	
	/* +2 for separator and null terminator */
	if(base_len+extend_len+2 > size)
	{
		fprintf(stderr, "'%s' + '%s' results in a too long path\n", base, extend);
		return __LINE__;
	}

	/* no base path, just use extend path then */
	if(base_len == 0)
	{
		memcpy(output, extend, extend_len+1);
		path_normalize(output);
		return 0;
	}
	
	/* copy base path */
	memcpy(output, base, base_len);
	
	/* append path separator if needed */
	if(!path_is_separator(base[base_len-1]))
	{
		output[base_len] = PATH_SEPARATOR;
		base_len++;
	}
	
	/* append the extra path, and null-terminator*/
	for(i = 0; i < extend_len+1; i++)
		output[base_len+i] = extend[i];
	
	/* normalize path and return success */
	path_normalize(output);
	return 0;
}
Ejemplo n.º 2
0
/*
 * Convert a system path into a VFS path.
 */
const char *fs_resolve(const char *system)
{
    static char path[MAXSTR];

    const char *p;

    /*
     * PhysicsFS will claim a file doesn't exist if its path uses a
     * directory separator other than a forward slash, even if that
     * separator is valid for the system. We'll oblige.
     */

    SAFECPY(path, system);

    path_normalize(path);

    if (fs_exists(path))
        return path;

    /* Chop off directories until we have a match. */

    p = path;

    while ((p = path_next_sep(p)))
    {
        /* Skip separator. */

        p += 1;

        if (fs_exists(p))
            return p;
    }

    return NULL;
}
Ejemplo n.º 3
0
fscrawl_t fsc_open(const char *path) {

    struct __fscrawl *f;
    char *npath;

    f = malloc(sizeof(struct __fscrawl));
    if (!f)
        return NULL;

    npath = path_normalize(path, NULL, 1);
    if (!npath)
        goto free;

    f->fts = _fts_open(npath, FTS_LOGICAL);
    free(npath);

    if (!f->fts) {
        logerrno(LOG_WARN, "ftc_open", errno);
        goto free;
    }

    f->ent.base = NULL;
    f->ent.name = NULL;
    f->ent.dir = 0;
    return f;
free:
    if (f)
        free(f);
    return NULL;
}
Ejemplo n.º 4
0
int lf_path_dir(lua_State *L)
{
	char buffer[1024];
	int n = lua_gettop(L);
	const char *path = 0;
	if(n < 1)
		luaL_error(L, "path_dir: incorrect number of arguments");

	path = lua_tostring(L, 1);
	if(!path)
		luaL_error(L, "path_dir: argument is not a string");
	
	/* check if we can take the easy way out */
	if(path_isnice(path))
	{
		lua_pushlstring(L, path, path_dir_length(path));
		return 1;
	}
	
	/* we must normalize the path as well */
	strncpy(buffer, path, sizeof(buffer));
	path_normalize(buffer);
	lua_pushlstring(L, buffer, path_dir_length(buffer));
	return 1;
}
Ejemplo n.º 5
0
depsRef depsScanForHeaders(const char *path)
{
	PATHSPLIT f;
	char buf[MAXJPATH];
	time_t time;
	HEADER *h;

	if (!inState(DEPS_STATE_INIT | DEPS_STATE_SEARCH))
	{
		if (!inState(DEPS_STATE_SEARCH)) setErr(DEPS_ERROR_NOT_SEARCH);
		if (!inState(DEPS_STATE_INIT)) setErr(DEPS_ERROR_NOT_INIT);
		return NULL;
	}
	setErr(0);

	path_split(path, &f);
	path_normalize(&f, NULL);
	path_tostring(&f, buf);

	timestamp(buf, &time);
	if (!time)
		return NULL;

	h = headers(buf, time);
	return (depsRef) h;
}
Ejemplo n.º 6
0
int lf_path_normalize(lua_State *L)
{
	int n = lua_gettop(L);
	const char *path = 0;

	if(n != 1)
		luaL_error(L, "path_normalize: incorrect number of arguments");

	luaL_checktype(L, 1, LUA_TSTRING);
	
	path = lua_tostring(L, 1);
	
	if(path_isnice(path))
	{
		/* path is ok */
		lua_pushstring(L, path);
	}
	else
	{
		/* normalize and return */
		char buffer[2*1024];
		strcpy(buffer, path);
		path_normalize(buffer);
		lua_pushstring(L, buffer);
	}
	
	return 1;
}
Ejemplo n.º 7
0
Archivo: path.c Proyecto: crossmeta/sgi
char *
path_reltoabs( char *dir, char *basedir )
{
	char *absdir;

	/* check if the path starts with a / or
	 * is a remote path (i.e. contains  machine:/path/name ).
	 */
	if ( ( *dir != '/' ) && ( strchr(dir, ':') == 0 ) ) {
		char *absdir;
		absdir = ( char * )malloc( strlen( basedir )
					   +
					   1
					   +
					   strlen( dir )
					   +
					   1 );
		ASSERT( absdir );

		( void )sprintf( absdir, "%s/%s", basedir, dir );

		dir = absdir;
	}

	if ( strchr(dir, ':') == 0 ) {
		absdir = path_normalize( dir );
	} else {
		absdir = ( char * )malloc( strlen( dir )  + 1);
		( void )sprintf( absdir, "%s", dir);
	}

	return absdir;
}
Ejemplo n.º 8
0
static int addwatch(const char *path, const char *name) {

    fscrawl_t f;
    char *npath = path_normalize(path, name, 1);

    if (!npath)
        return -1;

    if (inotify_watch(npath) < 0)
        goto clean;

    f = fsc_open(npath);
    if (!f)
        goto clean;

    for(;;) {
        notify_event *ev;
        fs_entry *ent = fsc_read(f);

        if (!ent)
            break;

        ev = notify_event_new();

        notify_event_set_type(ev, NOTIFY_CREATE);
        notify_event_set_path(ev, ent->base);
        notify_event_set_filename(ev, ent->name);
        notify_event_set_dir(ev, ent->dir);

        if (ev->dir) {
            char *fullpath = path_normalize(ev->path, ent->name, 1);
            if (fullpath && inotify_watch(fullpath) < 0)
                xfree(fullpath);
        }

        queue_enqueue(init_ev_q, ev);
    }
    fsc_close(f);

    return 1;
clean:
    xfree(npath);
    return -1;
}
Ejemplo n.º 9
0
static void windows_tz_to_tzid(char *buf, int max, Str name)
{
    Tok tk;
    char *path = path_normalize(NULL, fs->fox_home, "data" SEP_S "windows-tz.txt", -1, NULL);
    char *ini_buf = read_from_file(NULL, path, NULL);

    free(path);
    if (buf == NULL) {
        goto ERROR_END;
    }

    Tok_simple_init(&tk, ini_buf);
    Tok_simple_next(&tk);

    for (;;) {
        switch (tk.v.type) {
        case TL_STR:
            if (str_eq(tk.str_val.p, tk.str_val.size, name.p, name.size)) {
                Tok_simple_next(&tk);
                if (tk.v.type != T_LET) {
                    goto ERROR_END;
                }
                Tok_simple_next(&tk);
                if (tk.v.type != TL_STR) {
                    goto ERROR_END;
                }
                memcpy(buf, tk.str_val.p, tk.str_val.size);
                buf[tk.str_val.size] = '\0';
                free(ini_buf);
                return;
            } else {
                // 行末まで飛ばす
                while (tk.v.type == T_LET || tk.v.type == TL_STR) {
                    Tok_simple_next(&tk);
                }
            }
            break;
        case T_NL:
        case T_SEMICL:
            Tok_simple_next(&tk);
            break;
        case T_EOF:
            goto ERROR_END;
        default:
            fatal_errorf("Parse error at line %d (windows-tz.txt)", tk.v.line);
            break;
        }
    }

ERROR_END:
    strcpy(buf, "Etc/UTC");
    free(ini_buf);
}
Ejemplo n.º 10
0
void test(const char *path)
{
	PATHSPLIT f;
	char buf[1024];

	printf("> %s\n", path);
	path_split(path, &f);
	path_print(&f);
	path_normalize(&f, NULL);
	path_tostring(&f, buf);
	printf("< %s\n", buf);
}
Ejemplo n.º 11
0
static int rmwatch(const char *path, const char *name) {

    char *fpath;
    int ret;

    fpath = path_normalize(path, name, 1);

    if (!fpath)
        return -1;

    ret = inotify_ignore(fpath);
    free(fpath);
    return ret;
}
Ejemplo n.º 12
0
void search_adddir(const char *path)
{
	PATHSPLIT f;
	char buf[MAXJPATH];

	path_split(path, &f);
	path_normalize(&f, NULL); /* path_setcwd() should have been called */
	path_tostring(&f, buf);
	searchdirs = list_new(searchdirs, buf, 0);

#ifdef SEARCH_OPTIM
	/* searchhash is only valid for a fixed set of search directories */
	hashdone(searchhash);
	searchhash = 0;
#endif
}
Ejemplo n.º 13
0
static int pkcs8_dir_open(void *_handle, const char *config)
{
	if (!_handle || !config) {
		return DNSSEC_EINVAL;
	}

	pkcs8_dir_handle_t *handle = _handle;

	char *path = path_normalize(config);
	if (!path) {
		return DNSSEC_NOT_FOUND;
	}

	handle->dir_name = path;

	return DNSSEC_EOK;
}
Ejemplo n.º 14
0
void depsTimeStamp(const char *path, time_t *time)
{
	PATHSPLIT f;
	char buf[MAXJPATH];

	if (!inState(DEPS_STATE_INIT))
	{
		setErr(DEPS_ERROR_NOT_INIT);
		return;
	}
	setErr(0);

	path_split(path, &f);
	path_normalize(&f, NULL);
	path_tostring(&f, buf);

	timestamp(buf, time);
}
Ejemplo n.º 15
0
t_httpreq *
parse(char *input)
{
    char *inputdup, *token, *subtoken;
    char vbuf[MAX_VERSION_LENGTH];
    int n; /* For storing temporary value, i.e return codes */
    t_httpreq *req;

    inputdup = strdup(input);
    req = (t_httpreq*)malloc(sizeof(t_httpreq));
    if (req == NULL)
        fprintf(stderr,"malloc cannot allocate memory for new request");

     req->version = strdup(DEFAULT_VERSION);
     req->versionlen = 3;
     req->valid = 1;
     req->ifmodifiedsince = -1;

    /* Parse the HTTP method */
    if ((token = strtok(inputdup, " ")) == NULL) {
        req->valid = 0;
    } else {
        /* Note: method may be null if strdup fails
        * Below I tried to make sure that the method could not
        * be overflowed. The method should only be written to
        * the object if it is a valid method otherwise it should
        * be NULL
         */
        if (strlen(token) > MAX_METHOD_LENGTH) {
            req->method = NULL;
        } else {
            req->method = strdup(token);
        }

        if (req->method != NULL) {
            req->methodlen = strlen(token);
        } else {
            req->valid=0;
        }

        req->method_ident = ident_method(token);
        if (req->method_ident == HTTP_OTHER) {
            req->valid=0;
        }
    }

    /* Parse the request URL */
    if ((token = strtok(NULL, " ")) == NULL) {
        req->valid = 0;
    } else {
        if (strlen(token) > MAX_URI_LENGTH) {
            req->url = NULL;
        } else {
            req->url = strdup(path_normalize(token));
        }

        if (req->url != NULL) {
            req->urllen = strlen(token);
        } else {
            req->valid=0;
            req->urllen = -1;
        }
    }

    /* Parse the HTTP version */
    if ((token = strtok(NULL, " ")) == NULL) {
        req->valid = 0;
    } else {
        if (strncmp(token, "HTTP/", 5) != 0 ||  /* must start with HTTP/ */
            strlen(token) < 8 ||                /* must have a length of 8 */
            strchr(token+6, '.') == NULL) {     /* version must have a '.' */

            req->valid = 0;
        } else {
            token += 5;

            /* Parse major version */
            subtoken = strtok(token, ".");
            req->majorversion = atoi(subtoken);

            /* Parse minor version */
            if ((subtoken = strtok(NULL, ".")) == NULL) {
                req->valid = 0;
            } else {
                req->minorversion = atoi(subtoken);

                if ((n = sprintf(vbuf, "%d.%d",
                    req->majorversion, req->minorversion)) > 0) {

                    /* Free default version that was allocated */
                    free(req->version);

                    /* Note: Version may be null if strdup fails */
                    req->version = strdup(vbuf);
                    if (req->version != NULL) {
                        req->versionlen = strlen(vbuf);
                    } else {
                        req->versionlen = -1;
                    }
                }
            }
        }
    }

    /* For no we need this to */
    req->content = 1;
    free(inputdup);
    return req;
}
Ejemplo n.º 16
0
const char *search(const char *source, const char *_header, time_t *time)
{
	PATHNAME f[1];
	char buf[MAXJPATH];
	char buf2[MAXSYM], *header = buf2;
	char buf3[MAXJPATH];
	int system = (_header[0] == '<');
	LIST *list = searchdirs->next;
	
	/* D support */
	int dMode=0;
	int fnlen=strlen(source);
	if(source[fnlen-2]=='.' && source[fnlen-1]=='d')
		dMode=1;

	/* <foo.h> --> foo.h */
	strcpy(header, _header + 1);
	header[strlen(header) - 1] = '\0';

	/* src/foo.c --> src */
	path_parse(source, f);
	path_parent(f);
	path_build(f, buf3, 1);

	/* C::B patch: Fix bug with usage of root folder */
# if PATH_DELIM == '\\'
	/* Special case for D:/ - dirname is D:/, not "D:" */
	if ((strlen(buf3)==3) && (buf3[1]==':') && ((buf3[2]=='\\') || (buf3[2]=='/')))
		buf3[2] = 0;
# endif

	if (DEBUG_SEARCH)
		printf( "search %s\n  included by %s\n", _header, source);

#ifdef SEARCH_OPTIM
	{
		char key[MAXJPATH] = "";
		SEARCH search, *s = &search;
		if (!system)
		{
			strcpy(key, buf3);
			strcat(key, ",");
		}
		strcat(key, _header);
		s->key = key;
		if (!searchhash)
			searchhash = hashinit(sizeof(SEARCH), "search");
		if (hashcheck(searchhash, (HASHDATA **)&s))
		{
			if (DEBUG_SEARCH)
				printf("  %s: %s [CACHED]\n", _header, s->time ? s->path : "*missing*" );
			*time = s->time;
			return s->path;
		}
	}
#endif

	/* If this is "foo.h" not <foo.h> then set the first search directory
	 * to the including file's directory */
	if (!system)
	{
		searchdirs->string = buf3;
		list = searchdirs;
	}

	path_parse(header, f);

	f->f_grist.ptr = 0;
	f->f_grist.len = 0;
	
	for (; list; list = list->next)
	{
		f->f_root.ptr = list->string;
		f->f_root.len = strlen(list->string);

		path_build(f, buf, 1);

{
PATHSPLIT f;
char buf2[MAXJPATH];
path_split(buf, &f);
path_normalize(&f, NULL);
path_tostring(&f, buf2);
strcpy(buf, buf2);
}

		if (DEBUG_SEARCH)
			printf("  %s: %s [TRY]\n", _header, buf);

		timestamp(buf, time);

#ifdef SEARCH_OPTIM
		if (*time)
		{
			char key[MAXJPATH] = "";
			SEARCH search, *s = &search;
			if (!system)
			{
				strcpy(key, buf3);
				strcat(key, ",");
			}
			strcat(key, _header);
			s->key = newstr(key);
			s->time = *time;
			s->path = newstr(buf);
			(void) hashenter(searchhash, (HASHDATA **)&s);
		}
#endif

		if (*time)
			return newstr(buf);
	}

	if(!dMode)
	{
#ifdef SEARCH_OPTIM
		/* remember that this file could not be found */
		{
			char key[MAXJPATH] = "";
			SEARCH search, *s = &search;
			if (!system)
			{
				strcpy(key, buf3);
				strcat(key, ",");
			}
			strcat(key, _header);
			s->key = newstr(key);
			s->time = 0;
			s->path = NULL;
			(void) hashenter(searchhash, (HASHDATA **)&s);
		}
#endif

		/* C compilers do *not* look in the current directory for #include files */
		*time = 0;
		return NULL;
	}
	/* D support (look in current directory) */
	else
	{
		f->f_root.ptr = 0;
		f->f_root.len = 0;

		path_build( f, buf, 1 );

{
PATHSPLIT f;
char buf2[MAXJPATH];
path_split(buf, &f);
path_normalize(&f, NULL);
path_tostring(&f, buf2);
strcpy(buf, buf2);
}

		if( DEBUG_SEARCH )
			printf( "search %s: %s\n", _header, buf );

		timestamp( buf, time );


#ifdef SEARCH_OPTIM
		if (*time)
		{
			char key[MAXJPATH] = "";
			SEARCH search, *s = &search;
			if (!system)
			{
				strcpy(key, buf3);
				strcat(key, ",");
			}
			strcat(key, _header);
			s->key = newstr(key);
			s->time = *time;
			s->path = newstr(buf);
			(void) hashenter(searchhash, (HASHDATA **)&s);
		}
#endif

		if (*time)
			return newstr(buf);
		
#ifdef SEARCH_OPTIM
		/* remember that this file could not be found */
		{
			char key[MAXJPATH] = "";
			SEARCH search, *s = &search;
			if (!system)
			{
				strcpy(key, buf3);
				strcat(key, ",");
			}
			strcat(key, _header);
			s->key = newstr(key);
			s->time = 0;
			s->path = NULL;
			(void) hashenter(searchhash, (HASHDATA **)&s);
		}
#endif

		*time = 0;
		return NULL;
	}
}
Ejemplo n.º 17
0
Archivo: dep_cpp.c Proyecto: malind/bam
static int dependency_cpp_callback(struct NODE *node, void *user, const char *filename, int sys)
{
	struct CPPDEPINFO *depinfo = (struct CPPDEPINFO *)user;
	struct CPPDEPINFO recurseinfo;
	char buf[MAX_PATH_LENGTH];
	int check_system = sys;

	int found = 0;
	struct NODE *depnode = NULL;
	time_t timestamp = 0;
	
	
	if(!sys)
	{
		/* "normal.header" */
		int flen = strlen(node->filename)-1;
		while(flen)
		{
			if(node->filename[flen] == '/')
				break;
			flen--;
		}
		path_join(node->filename, flen, filename, -1, buf, sizeof(buf));
		
		if(node_findfile(node->graph, buf, &depnode, &timestamp))
			found = 1;
		else
		{
			/* file does not exist */
			check_system = 1;
		}
	}

	if(check_system)
	{
		/* <system.header> */
		if(path_isabs(filename))
		{
			if(node_findfile(node->graph, filename, &depnode, &timestamp))
			{
				strcpy(buf, filename);
				found = 1;
			}
		}
		else
		{
			struct STRINGLIST *cur;
			int flen = strlen(filename);

			for(cur = depinfo->paths; cur; cur = cur->next)
			{
				path_join(cur->str, cur->len, filename, flen, buf, sizeof(buf));
				if(node_findfile(node->graph, buf, &depnode, &timestamp))
				{
					found = 1;
					break;
				}
			}
		}
	}

	/* */
	if(found)
	{
		path_normalize(buf);
		if(!depnode)
			node_create(&depnode, node->graph, buf, NULL, timestamp);
		if(node_add_dependency (node, depnode) == NULL)
			return 2;

		if(!depnode)
			return 3;
	
		/* do the dependency walk */
		if(!depnode->depchecked)
		{
			recurseinfo.paths = depinfo->paths;
			recurseinfo.context = depinfo->context;
			if(dependency_cpp_run(depinfo->context, depnode, dependency_cpp_callback, &recurseinfo) != 0)
				return 4;
		}
	}
		
	return 0;
}
Ejemplo n.º 18
0
int
super_html_read_serve(
        FILE *flog,
        const unsigned char *path,
        const struct ejudge_cfg *config,
        const struct contest_desc *cnts,
        struct sid_state *sstate)
{
  struct stat sb;
  int cond_count = 0, total, i, cur_id, j, arch, k;
  struct generic_section_config *pg;
  struct section_global_data *global;
  struct section_problem_data *prob, *aprob;
  struct section_tester_data *tst, *atst;
  struct section_language_data *lang;
  size_t vm_size, st_size;
  size_t *mem_lims, *st_lims;
  int *mem_cnt, *st_cnt;
  //int mem_u, st_u, max_i;
  path_t check_cmd = { 0 };
  FILE *fuh;
  char *fuh_text = 0;
  size_t fuh_size = 0;
  path_t cs_spool_dir;
  path_t conf_dir;
  path_t tmppath;
  unsigned char *prob_no_any = 0;
  size_t cs_spool_dir_len = 0;
  unsigned char cs_conf_file[PATH_MAX];

  if (!cnts) {
    fprintf(flog, "No contest XML description\n");
    return -1;
  }
  if (!cnts->conf_dir || !*cnts->conf_dir) {
    snprintf(conf_dir, sizeof(conf_dir), "%s/%s", cnts->root_dir, "conf");
  } else if (!os_IsAbsolutePath(cnts->conf_dir)) {
    snprintf(conf_dir, sizeof(conf_dir), "%s/%s", cnts->root_dir, cnts->conf_dir);
  } else {
    snprintf(conf_dir, sizeof(conf_dir), "%s", cnts->conf_dir);
  }

  if (stat(path, &sb) < 0) {
    // file do not exist
    return 0;
  }
  if (!S_ISREG(sb.st_mode)) {
    fprintf(flog, "File `%s' not a regular file\n", path);
    return -1;
  }
  if (access(path, R_OK) < 0) {
    fprintf(flog, "File `%s' is not readable\n", path);
    return -1;
  }

  // FIXME: redirect output?
  if (!(sstate->cfg = prepare_parse_config_file(path, &cond_count))) {
    fprintf(flog, "Parsing of `%s' failed\n", path);
    return -1;
  }
  if (cond_count > 0) {
    fprintf(flog, "The configuration file uses conditional compilation directives\n");
    return -1;
  }

  // find global section
  for (pg = sstate->cfg; pg; pg = pg->next)
    if (!pg->name[0] || !strcmp(pg->name, "global"))
      break;
  if (!pg) {
    fprintf(flog, "The global section is not defined\n");
    return -1;
  }
  global = sstate->global = (struct section_global_data *) pg;

  // set up the default value of the root_dir
  if (!global->root_dir[0]) {
    snprintf(global->root_dir, sizeof(global->root_dir), "%06d",
             global->contest_id);
  }
  if (!os_IsAbsolutePath(global->root_dir) && config
      && config->contests_home_dir
      && os_IsAbsolutePath(config->contests_home_dir)) {
    snprintf(tmppath, sizeof(tmppath), "%s/%s", config->contests_home_dir,
             global->root_dir);
    snprintf(global->root_dir, sizeof(global->root_dir), "%s", tmppath);
  }
#if defined EJUDGE_CONTESTS_HOME_DIR
  if (!os_IsAbsolutePath(global->root_dir)) {
    snprintf(tmppath, sizeof(tmppath), "%s/%s", EJUDGE_CONTESTS_HOME_DIR,
             global->root_dir);
    snprintf(global->root_dir, sizeof(global->root_dir), "%s", tmppath);
  }
#endif
  if (!os_IsAbsolutePath(global->root_dir)) {
    err("global.root_dir must be absolute directory!");
    return -1;
  }

  // check variables that we don't want to be ever set
  if (prepare_check_forbidden_global(flog, global) < 0) return -1;

  // contest_id, conf_dir, root_dir must match
  if (global->contest_id != cnts->id) {
    fprintf(flog, "contest_id does not match\n");
    return -1;
  }
  if (strcmp(global->root_dir, cnts->root_dir)) {
    fprintf(flog, "root_dir does not match\n");
    return -1;
  }
  /*
  if ((!cnts->conf_dir && global->conf_dir)
      || (cnts->conf_dir && strcmp(cnts->conf_dir, global->conf_dir))) {
    fprintf(flog, "conf_dir does not match\n");
    return -1;
  } 
  */

  // compile server must be used
  if (!global->compile_dir[0]) {
    fprintf(flog, "compilation server is not used\n");
    return -1;
  }
  if (!os_IsAbsolutePath(global->compile_dir)) {
    snprintf(tmppath, sizeof(tmppath), "%s/var/%s", global->root_dir,
             global->compile_dir);
    path_normalize(tmppath, sizeof(tmppath));
    snprintf(global->compile_dir, sizeof(global->compile_dir), "%s", tmppath);
  }
  if (!config->compile_home_dir) {
    fprintf(flog, "compile server home dir is not set\n");
    return -1;
  }
  // cut off "/var/compile" suffix from the compile dir
  snprintf(cs_spool_dir, sizeof(cs_spool_dir), "%s", global->compile_dir);
  cs_spool_dir_len = strlen(cs_spool_dir);
  if (cs_spool_dir_len < sizeof(compile_dir_suffix)
      || strcmp(cs_spool_dir+cs_spool_dir_len-sizeof(compile_dir_suffix)+1,
                compile_dir_suffix) != 0) {
    fprintf(flog, "invalid `compile_dir' %s\n", cs_spool_dir);
    return -1;
  }
  cs_spool_dir[cs_spool_dir_len-sizeof(compile_dir_suffix)+1] = 0;
  sstate->compile_home_dir = xstrdup(cs_spool_dir);
  //fprintf(stderr, "compile_home_dir>>%s<<\n", sstate->compile_home_dir);
  /*
  snprintf(cs_spool_dir, sizeof(cs_spool_dir), "%s/var/compile",
           config->compile_home_dir);
  if (strcmp(cs_spool_dir, global->compile_dir)) {
    fprintf(flog, "non-default compilation server is used\n");
    return -1;
  }
  */

  prepare_set_global_defaults(global);
  if (global->stand2_file_name[0]) sstate->enable_stand2 = 1;
  if (global->plog_file_name[0]) sstate->enable_plog = 1;
  if (global->stand_extra_format[0]) sstate->enable_extra_col = 1;

  fuh = open_memstream(&fuh_text, &fuh_size);
  prepare_unparse_unhandled_global(fuh, global);
  close_memstream(fuh); fuh = 0;
  if (fuh_text && *fuh_text) {
    global->unhandled_vars = fuh_text;
  } else {
    xfree(fuh_text);
  }
  fuh_text = 0; fuh_size = 0;

  // collect languages
  total = 0; cur_id = 0;
  for (pg = sstate->cfg; pg; pg = pg->next) {
    if (strcmp(pg->name, "language") != 0) continue;
    lang = (struct section_language_data*) pg;
    if (!lang->id) lang->id = cur_id + 1;
    cur_id = lang->id;
    if (lang->id <= 0 || lang->id > EJ_MAX_LANG_ID) {
      fprintf(flog, "Invalid language ID\n");
      return -1;
    }
    if (lang->id >= total) total = lang->id + 1;
  }

  sstate->lang_a = 0;
  sstate->langs = 0;
  sstate->loc_cs_map = 0;
  sstate->lang_opts = 0;
  sstate->lang_flags = 0;
  if (total > 0) {
    sstate->lang_a = 4;
    while (total > sstate->lang_a) sstate->lang_a *= 2;
    XCALLOC(sstate->langs, sstate->lang_a);
    XCALLOC(sstate->loc_cs_map, sstate->lang_a);
    XCALLOC(sstate->lang_opts, sstate->lang_a);
    XCALLOC(sstate->lang_flags, sstate->lang_a);
    for (pg = sstate->cfg; pg; pg = pg->next) {
      if (strcmp(pg->name, "language") != 0) continue;
      lang = (struct section_language_data*) pg;
      if (sstate->langs[lang->id]) {
        fprintf(flog, "Duplicated language ID %d\n", lang->id);
        return -1;
      }
      sstate->langs[lang->id] = lang;
    }
  }

  // load the compilation server state and establish correspondence
  if (super_load_cs_languages(config, sstate, global->extra_compile_dirs, 0,
                              cs_conf_file, sizeof(cs_conf_file)) < 0) {
    fprintf(flog, "Failed to load compilation server configuration\n");
    return -1;
  }

  for (i = 1; i < sstate->lang_a; i++) {
    if (!(lang = sstate->langs[i])) continue;
    if (!lang->compile_id) lang->compile_id = lang->id;

    if (prepare_check_forbidden_lang(flog, lang) < 0)
      return -1;

    /*
    if (lang->compile_id <= 0 || lang->compile_id >= sstate->cs_lang_total
        || !sstate->cs_langs[lang->compile_id]) {
    }
    */
    // improve error messaging
    if (lang->compile_id > 0 && lang->compile_id < sstate->cs_lang_total
        && sstate->cs_langs[lang->compile_id]
        && strcmp(lang->short_name, sstate->cs_langs[lang->compile_id]->short_name) != 0) {
      fprintf(flog,
              "contest configuration file '%s' specifies language short name '%s' for language %d\n"
              "and it is different from language short name '%s' in compilation configuration file '%s'\n",
              path, lang->short_name, lang->compile_id,
              sstate->cs_langs[lang->compile_id]->short_name,
              cs_conf_file);
      return -1;
    }

    if (lang->compile_id <= 0
        || lang->compile_id >= sstate->cs_lang_total
        || !sstate->cs_langs[lang->compile_id]
        || strcmp(lang->short_name, sstate->cs_langs[lang->compile_id]->short_name) != 0) {
      lang->compile_id = 0;
    }
    for (int j = 1; j < sstate->cs_lang_total; ++j) {
      if (sstate->cs_langs[j]
          && !strcmp(lang->short_name, sstate->cs_langs[j]->short_name)) {
        lang->compile_id = j;
        break;
      }
    }
    if (lang->compile_id <= 0) {
      fprintf(flog, "Invalid compile_id\n");
      return -1;
    }

    sstate->loc_cs_map[lang->id] = lang->compile_id;
    sstate->cs_loc_map[lang->compile_id] = lang->id;

    fuh = open_memstream(&fuh_text, &fuh_size);
    prepare_unparse_unhandled_lang(fuh, lang);
    close_memstream(fuh); fuh = 0;
    if (fuh_text && *fuh_text) {
      lang->unhandled_vars = fuh_text;
    } else {
      xfree(fuh_text);
    }
    fuh_text = 0; fuh_size = 0;

    if (lang->compiler_env) {
      for (j = 0; lang->compiler_env[j]; j++) {
        if (!strncmp(lang->compiler_env[j], "EJUDGE_FLAGS=", 13)) {
          sstate->lang_opts[lang->id] = xstrmerge1(sstate->lang_opts[lang->id],
                                                   lang->compiler_env[j] + 13);
        }
      }
      for (--j; j >= 0; --j) {
        if (!strncmp(lang->compiler_env[j], "EJUDGE_FLAGS=", 13)) {
          xfree(lang->compiler_env[j]); lang->compiler_env[j] = 0;
          for (k = j + 1; lang->compiler_env[k]; k++) {
            lang->compiler_env[k - 1] = lang->compiler_env[k];
          }
          lang->compiler_env[k - 1] = lang->compiler_env[k];
        }        
      }
    }
  }

  // collect abstract problems
  for (pg = sstate->cfg, total = 0; pg; pg = pg->next) {
    if (!strcmp(pg->name, "problem")
        && (prob = (struct section_problem_data*) pg)->abstract)
      total++;
  }

  sstate->aprob_a = 0;
  sstate->aprob_u = 0;
  sstate->aprobs = 0;
  sstate->aprob_flags = 0;
  if (total) {
    sstate->aprob_a = 4;
    while (total > sstate->aprob_a) sstate->aprob_a *= 2;
    XCALLOC(sstate->aprobs, sstate->aprob_a);
    XCALLOC(sstate->aprob_flags, sstate->aprob_a);
    for (pg = sstate->cfg, i = 0; pg; pg = pg->next) {
      if (strcmp(pg->name, "problem") != 0) continue;
      prob = (struct section_problem_data*) pg;
      if (!prob->abstract) continue;
      sstate->aprobs[i++] = prob;
      if (!prob->short_name[0]) {
        fprintf(flog, "Abstract problem must have `short_name' field set\n");
        return -1;
      }
      if (prob->super[0]) {
        fprintf(flog, "Abstract problem must not have a superproblem\n");
        return -1;
      }

      if (prepare_check_forbidden_prob(flog, prob) < 0)
        return -1;

      prepare_set_abstr_problem_defaults(prob, global);

      fuh = open_memstream(&fuh_text, &fuh_size);
      prepare_unparse_unhandled_prob(fuh, prob, global);
      close_memstream(fuh); fuh = 0;
      if (fuh_text && *fuh_text) {
        prob->unhandled_vars = fuh_text;
      } else {
        xfree(fuh_text);
      }
      fuh_text = 0; fuh_size = 0;
    }
    ASSERT(i == total);
    sstate->aprob_u = total;
  }

  // collect concrete problems
  total = 0; cur_id = 0;
  for (pg = sstate->cfg; pg; pg = pg->next) {
    if (strcmp(pg->name, "problem") != 0) continue;
    prob = (struct section_problem_data*) pg;
    if (prob->abstract) continue;
    if (!prob->id) prob->id = cur_id + 1;
    cur_id = prob->id;
    if (prob->id <= 0 || prob->id > EJ_MAX_PROB_ID) {
      fprintf(flog, "Invalid problem ID\n");
      return -1;
    }
    if (prob->id >= total) total = prob->id + 1;
  }

  sstate->probs = 0;
  sstate->prob_a = 0;
  sstate->prob_flags = 0;
  if (total > 0) {
    sstate->prob_a = 4;
    while (total > sstate->prob_a) sstate->prob_a *= 2;
    XCALLOC(sstate->probs, sstate->prob_a);
    XCALLOC(sstate->prob_flags, sstate->prob_a);
    XALLOCAZ(prob_no_any, sstate->prob_a);
    for (pg = sstate->cfg; pg; pg = pg->next) {
      if (strcmp(pg->name, "problem") != 0) continue;
      prob = (struct section_problem_data*) pg;
      if (prob->abstract) continue;
      if (sstate->probs[prob->id]) {
        fprintf(flog, "Duplicated problem id %d\n", prob->id);
        return -1;
      }
      sstate->probs[prob->id] = prob;
      if (prob->super[0]) {
        for (i = 0; i < sstate->aprob_u; i++)
          if (!strcmp(prob->super, sstate->aprobs[i]->short_name))
            break;
        if (i == sstate->aprob_u) {
          fprintf(flog, "Abstract problem `%s' not found\n", prob->super);
          return -1;
        }
      }
      if (prepare_check_forbidden_prob(flog, prob) < 0)
        return -1;

      prepare_set_concr_problem_defaults(prob, global);

      fuh = open_memstream(&fuh_text, &fuh_size);
      prepare_unparse_unhandled_prob(fuh, prob, global);
      close_memstream(fuh); fuh = 0;
      if (fuh_text && *fuh_text) {
        prob->unhandled_vars = fuh_text;
      } else {
        xfree(fuh_text);
      }
      fuh_text = 0; fuh_size = 0;
    }
  }

  // collect abstract testers
  total = 0;
  for (pg = sstate->cfg; pg; pg = pg->next) {
    if (strcmp(pg->name, "tester")) continue;
    tst = (struct section_tester_data*) pg;
    if (!tst->abstract) continue;
    // check, that we know such abstract tester
    if ((arch = prepare_unparse_is_supported_tester(tst->name)) < 0) {
      fprintf(flog, "Unsupported abstract tester `%s'\n", tst->name);
      return -1;
    }
    if ((i = prepare_unparse_is_supported_arch(tst->arch)) < 0) {
      fprintf(flog, "Unsupported tester architecture `%s'\n", tst->arch);
      return -1;
    }
    if (i != arch) {
      fprintf(flog, "Abstract tester name does not match tester arch\n");
      return -1;
    }
    if (tst->id) {
      fprintf(flog, "Abstract tester must not define tester ID\n");
      return -1;
    }
    if (tst->problem_name[0]) {
      fprintf(flog, "Abstract tester must not define problem name\n");
      return -1;
    }
    if (tst->problem) {
      fprintf(flog, "Abstract tester must not define problem ID\n");
      return -1;
    }
    total++;
  }

  /* Relax, try to work without testers... */
  /*
  if (!total) {
    fprintf(flog, "No abstract testers defined\n");
    return -1;
  }
  */

  sstate->atester_total = total;
  if (total > 0) {
    XCALLOC(sstate->atesters, sstate->atester_total);
    for (pg = sstate->cfg, i = 0; pg; pg = pg->next) {
      if (strcmp(pg->name, "tester")) continue;
      tst = (struct section_tester_data*) pg;
      if (!tst->abstract) continue;
      sstate->atesters[i++] = tst;
      // FIXME: check for unhandled fields
    }
  }

  // collect concrete testers, attempting to recover vm limit, stack limit
  // and checker name
  total = 0; cur_id = 0;
  for (pg = sstate->cfg; pg; pg = pg->next) {
    if (strcmp(pg->name, "tester") != 0) continue;
    tst = (struct section_tester_data*) pg;
    if (tst->abstract) continue;
    if (!tst->id) tst->id = cur_id + 1;
    cur_id = tst->id;
    if (tst->id <= 0 || tst->id > EJ_MAX_TESTER) {
      fprintf(flog, "Invalid tester ID\n");
      return -1;
    }
    if (tst->id >= total) total = tst->id + 1;
  }

  sstate->tester_total = total;
  if (total > 0) {
    XCALLOC(sstate->testers, sstate->tester_total);
  }
  for (pg = sstate->cfg; pg; pg = pg->next) {
    if (strcmp(pg->name, "tester") != 0) continue;
    tst = (struct section_tester_data*) pg;
    if (tst->abstract) continue;
    if (sstate->testers[tst->id]) {
      fprintf(flog, "Duplicated tester ID %d\n", tst->id);
      return -1;
    }
    sstate->testers[tst->id] = tst;
    if (tst->super && tst->super[0] && tst->super[1]) {
      fprintf(flog, "Tester %d has several supertesters\n", tst->id);
      return -1;
    }
    atst = 0;
    if (tst->super) {
      for (i = 0; i < sstate->atester_total; i++)
        if (!strcmp(sstate->atesters[i]->name, tst->super[0]))
          break;
      if (i == sstate->atester_total) {
        fprintf(flog, "Abstract tester `%s' not found\n", tst->super[0]);
        return -1;
      }
      atst = sstate->atesters[i];
    }
    if (tst->any) {
      continue;
    }
    prob = 0;
    if (tst->problem && tst->problem_name[0]) {
      fprintf(flog, "Both problem and problem_name fields cannot be set\n");
      return -1;
    } else if (tst->problem) {
      if (tst->problem <= 0 || tst->problem >= sstate->prob_a
          || !sstate->probs[tst->problem]) {
        fprintf(flog, "problem %d is invalid\n", tst->problem);
        return -1;
      }
      prob = sstate->probs[tst->problem];
    } else if (tst->problem_name[0]) {
      for (i = 1; i < sstate->prob_a; i++)
        if (sstate->probs[i]
            && !strcmp(sstate->probs[i]->short_name, tst->problem_name))
          break;
      if (i == sstate->prob_a) {
        fprintf(flog, "Problem `%s' does not exist\n", tst->problem_name);
        return -1;
      }
      prob = sstate->probs[i];
    } else {
      fprintf(flog, "Neither problem not problem_name are set\n");
      return -1;
    }
    prob_no_any[prob->id] = 1;

    vm_size = tst->max_vm_size;
    if (vm_size == -1L && atst) vm_size = atst->max_vm_size;
    st_size = tst->max_stack_size;
    if (st_size == -1L && atst) st_size = atst->max_stack_size;
    if (vm_size != -1L) {
      if (prob->max_vm_size == -1L) prob->max_vm_size = vm_size;
      if (prob->max_vm_size != vm_size) {
        fprintf(flog, "Conflicting max_vm_size specifications for problem `%s'\n",
                prob->short_name);
        return -1;
      }
    }
    if (st_size != -1L) {
      if (prob->max_stack_size == -1L) prob->max_stack_size = st_size;
      if (prob->max_stack_size != st_size) {
        fprintf(flog, "Conflicting max_stack_size specifications for problem `%s'\n",
                prob->short_name);
        return -1;
      }
    }
  }

  for (i = 0; i < sstate->tester_total; i++) {
    if (!(tst = sstate->testers[i])) continue;

    atst = 0;
    if (tst->super) {
      for (j = 0; j < sstate->atester_total; j++)
        if (!strcmp(sstate->atesters[j]->name, tst->super[0]))
          break;
      if (j == sstate->atester_total) {
        fprintf(flog, "Abstract tester `%s' not found\n", tst->super[0]);
        return -1;
      }
      atst = sstate->atesters[j];
    }

    if (!tst->any) continue;

    for (j = 0; j < sstate->prob_a; j++) {
      if (!(prob = sstate->probs[j])) continue;
      if (prob_no_any[j]) continue;

      vm_size = tst->max_vm_size;
      if (vm_size == -1L && atst) vm_size = atst->max_vm_size;
      st_size = tst->max_stack_size;
      if (st_size == -1L && atst) st_size = atst->max_stack_size;
      if (vm_size != -1L) {
        if (prob->max_vm_size == -1L) prob->max_vm_size = vm_size;
        if (prob->max_vm_size != vm_size) {
          fprintf(flog, "Conflicting max_vm_size specifications for problem `%s'\n",
                  prob->short_name);
          return -1;
        }
      }
      if (st_size != -1L) {
        if (prob->max_stack_size == -1L) prob->max_stack_size = st_size;
        if (prob->max_stack_size != st_size) {
          fprintf(flog, "Conflicting max_stack_size specifications for problem `%s'\n",
                  prob->short_name);
          return -1;
        }
      }
    }
  }

  XALLOCA(mem_lims, sstate->prob_a);
  XALLOCA(st_lims, sstate->prob_a);
  XALLOCA(mem_cnt, sstate->prob_a);
  XALLOCA(st_cnt, sstate->prob_a);

  // propagate most used memory limit to superproblem
  /*
  for (i = 0; i < sstate->aprob_u; i++) {
    aprob = sstate->aprobs[i];
    mem_u = 0;
    st_u = 0;
    XMEMZERO(mem_cnt, sstate->prob_a);
    XMEMZERO(st_cnt, sstate->prob_a);
    for (j = 1; j < sstate->prob_a; j++) {
      if (!(prob = sstate->probs[j]) || !prob->super[0]
          || strcmp(prob->super, aprob->short_name)) continue;
      if (prob->max_vm_size != -1L) {
        for (k = 0; k < mem_u; k++)
          if (mem_lims[k] == prob->max_vm_size)
            break;
        if (k == mem_u) mem_u++;
        mem_lims[k] = prob->max_vm_size;
        mem_cnt[k]++;
      }
      if (prob->max_stack_size != -1L) {
        for (k = 0; k < st_u; k++)
          if (st_lims[k] == prob->max_stack_size)
            break;
        if (k == st_u) st_u++;
        st_lims[k] = prob->max_stack_size;
        st_cnt[k]++;
      }
    }
    if (mem_u > 0) {
      max_i = 0;
      for (i = 1; i < mem_u; i++)
        if (mem_cnt[i] > mem_cnt[max_i])
          max_i = i; 
      aprob->max_vm_size = mem_lims[max_i];
      for (j = 1; j < sstate->prob_a; j++) {
        if (!(prob = sstate->probs[j]) || !prob->super[0]
            || strcmp(prob->super, aprob->short_name)) continue;
        if (prob->max_vm_size == -1L) {
          prob->max_vm_size = 0;
        } else if (prob->max_vm_size == aprob->max_vm_size) {
          prob->max_vm_size = -1L;
        }
      }
    }
    if (st_u > 0) {
      max_i = 0;
      for (i = 1; i < st_u; i++)
        if (st_cnt[i] > st_cnt[max_i])
          max_i = i; 
      aprob->max_stack_size = st_lims[max_i];
      for (j = 1; j < sstate->prob_a; j++) {
        if (!(prob = sstate->probs[j]) || !prob->super[0]
            || strcmp(prob->super, aprob->short_name)) continue;
        if (prob->max_stack_size == -1L) {
          prob->max_stack_size = 0;
        } else if (prob->max_stack_size == aprob->max_stack_size) {
          prob->max_stack_size = -1L;
        }
      }
    }
  }
  */

  // assign this check_cmd to all abstract problems without check_cmd
  for (i = 0; i < sstate->aprob_u; i++)
    if (!(aprob = sstate->aprobs[i])->check_cmd[0])
      snprintf(aprob->check_cmd, sizeof(aprob->check_cmd), "%s", check_cmd);

  sstate->contest_start_cmd_text = do_load_file(conf_dir, global->contest_start_cmd);
  sstate->contest_stop_cmd_text = do_load_file(conf_dir, global->contest_stop_cmd);
  sstate->stand_header_text = do_load_file(conf_dir, global->stand_header_file);
  sstate->stand_footer_text = do_load_file(conf_dir, global->stand_footer_file);
  sstate->stand2_header_text = do_load_file(conf_dir, global->stand2_header_file);
  sstate->stand2_footer_text = do_load_file(conf_dir, global->stand2_footer_file);
  sstate->plog_header_text = do_load_file(conf_dir, global->plog_header_file);
  sstate->plog_footer_text = do_load_file(conf_dir, global->plog_footer_file);

  return 0;
}