/*-
 *  Copyright (c) 2001  Peter Pentchev
 *  All rights reserved.
 * 
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 *  SUCH DAMAGE.
 */

#include <sys/types.h>
#include <sys/stat.h>

#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "penv.h"
#include "pe_compat.h"
#include "pe_env.h"

__RINGID("$Ringlet: c/misc/penv/pe_env.c,v 1.5 2004/01/27 15:00:53 roam Exp $");

static pe_err_t	pe_env_parse(const char *str, char **pvar, char **pval);

static pe_err_t
pe_env_parse(const char *str, char **pvar, char **pval) {
	char *p, *var, *val;
	size_t lvar, lval;

	p = strchr(str, '=');
	if (p == str)
		return (PE_ERR_VAR_FMT);
	if (p == NULL) {
		/* Just a variable name: an empty file request */
		lvar = strlen(str);
		if (var = malloc(lvar + 1), var == NULL)
			return (PE_ERR_NOMEM);
		memcpy(var, str, lvar + 1);
		*pvar = var;
		*pval = NULL;
		return (PE_ERR_NONE);
	}

	/* Find the variable name */
	for (lvar = p - str; lvar != 1; lvar--)
		if (!isspace(str[lvar - 1]))
			break;
	if (lvar == 1)
		return (PE_ERR_VAR_FMT);
	/* ..and the value */
	lval = strlen(p + 1);

	/* Alloc memory */
	if (var = malloc(lvar + 1), var == NULL)
		return (PE_ERR_NOMEM);
	if (val = malloc(lval + 1), val == NULL) {
		free(var);
		return (PE_ERR_NOMEM);
	}
	memcpy(var, str, lvar);
	var[lvar] = '\0';
	memcpy(val, p + 1, lval);
	val[lval] = '\0';
	
	*pvar = var;
	*pval = val;
	return (PE_ERR_NONE);
}

pe_err_t
pe_c_setvar(int argc, char *argv[]) {
	int i;
	char *var, *val;
	FILE *fp;
	mode_t mask;
	pe_err_t r;

	if (argc < 1)
		usage();

	var = val = NULL;
	r = PE_ERR_NONE;

	if (pe_cenvdir == NULL)
		return (PE_ERR_INT);
	if (chdir(pe_cenvdir) == -1)
		return (PE_ERR_CHDIR);

	for (i = 0; i < argc; i++) {
		if (r = pe_env_parse(argv[i], &var, &val), r)
			break;
		if (chmod(var, 0600) == -1 && errno != ENOENT) {
			r = PE_ERR_FCHMOD;
			break;
		}
		mask = umask(0777);
		fp = fopen(var, "w");
		umask(mask);
		if (fp == NULL) {
			r = PE_ERR_FOPEN;
			break;
		}
		if (fchmod(fileno(fp), pe_filemode) == -1) {
			fclose(fp);
			unlink(var);
			r = PE_ERR_FCHMOD;
			break;
		}
		if (val != NULL)
			fprintf(fp, "%s\n", val);
		fclose(fp);
	}
	
	free(var);
	free(val);
	return (r);
}

pe_err_t
pe_c_resetvar(int argc, char *argv[]) {
	int i;

	if (argc < 1)
		usage();

	if (pe_cenvdir == NULL)
		return (PE_ERR_INT);
	if (chdir(pe_cenvdir) == -1)
		return (PE_ERR_CHDIR);

	for (i = 0; i < argc; i++)
		if (unlink(argv[i]) == -1)
			return (PE_ERR_UNLINK);
	
	return (PE_ERR_NONE);
}

pe_err_t
pe_c_envlist(int argc, char *argv[] __unused) {
	DIR *d;
	struct dirent *e;
	struct stat sb;
	FILE *fp;
	char *buf;
	size_t sz;
	pe_err_t r;

	if (argc > 0)
		usage();

	if (chdir(pe_cenvdir) == -1)
		return (PE_ERR_NONE);
	if (d = opendir("."), d == NULL)
		return (PE_ERR_OPENDIR);

	while (e = readdir(d), e != NULL) {
		if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, ".."))
			continue;
		if (stat(e->d_name, &sb) == -1)
			continue;
		if (!S_ISREG(sb.st_mode))
			continue;
		if (sb.st_size == 0) {
			printf("%s\n", e->d_name);
			continue;
		}

		if (fp = fopen(e->d_name, "rt"), fp == NULL)
			continue;
		buf = NULL;
		r = pe_getline(fp, &buf, &sz);
		fclose(fp);
		if (r != PE_ERR_NONE) {
			free(buf);
			return (r);
		}

		while ((sz > 0) &&
		    ((buf[sz - 1] == '\r') || (buf[sz - 1] == '\n')))
			buf[--sz] = '\0';
		printf("%s=%.*s\n", e->d_name, (int)sz, buf);
		free(buf);
	}

	closedir(d);
	return (PE_ERR_NONE);
}


syntax highlighted by Code2HTML, v. 0.9.1