summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@derf.homelinux.org>2009-11-11 15:22:01 +0100
committerDaniel Friesel <derf@derf.homelinux.org>2009-11-11 15:22:01 +0100
commit12e78322c5fdd633c6582b8049ed8b412b275fd6 (patch)
tree82641c015580d3730633fd9139c4bfecc0323bdb
parent20bcc774686078cf7f5c58ef058ca2458b01086d (diff)
Simplified envstore (no need for linked lists)
from branch 'simple'
-rw-r--r--man/1/envstore4
-rw-r--r--src/envstore.c247
2 files changed, 98 insertions, 153 deletions
diff --git a/man/1/envstore b/man/1/envstore
index 2a65781..d3ae39a 100644
--- a/man/1/envstore
+++ b/man/1/envstore
@@ -39,8 +39,8 @@ By default /tmp/envstore\-\fIEUID\fR
.SH "LIMITATIONS"
Variable names or values must not contain null bytes or newlines.
.PP
-The current maximum length (in bytes) is 127 bytes for the variable name
-and 255 bytes for its content.
+The current maximum length (in bytes) is 255 bytes for the variable name
+and 1023 bytes for its content.
.SH "AUTHOR"
\fBenvstore\fR was written by Daniel Friesel <derf@derf.homelinux.org>
.PP
diff --git a/src/envstore.c b/src/envstore.c
index 171b786..7cb1f68 100644
--- a/src/envstore.c
+++ b/src/envstore.c
@@ -13,94 +13,18 @@
#include <sys/types.h>
#include <unistd.h>
-/*
- * This struct is part of a linked list and contains one shell parameter
- */
-
-struct parameter {
- char *name;
- char *content;
- struct parameter *next;
-};
-
-
-/*
- * Add element to linked list
- *
- * Parameters: list head (may be NULL), new list element
- * Returns new list head
- */
-
-static struct parameter * list_add(struct parameter *first, struct parameter *new) {
- new->next = first;
- first = new;
- return first;
-}
-
-
-/*
- * Remove element from linked list
- *
- * Parameters: list head, ->name part of element to remove
- * Returns new list head (may be NULL)
- */
-
-static struct parameter * list_remove(struct parameter *first, char *string) {
- struct parameter *cur = first;
- struct parameter *prev = NULL;
-
- while (cur != NULL) {
- if (strcmp(cur->name, string) == 0) {
-
- if (prev == NULL)
- return cur->next;
-
- prev->next = cur->next;
- return first;
- }
- prev = cur;
- cur = cur->next;
- }
- return first;
-}
-
-
-static void store_save(struct parameter *first, char *file) {
- struct parameter *cur = first;
- FILE *fp;
- char *tmpfile = malloc(strlen(file) + 5);
-
- if (tmpfile == NULL)
- err(EXIT_FAILURE, "malloc");
-
- if (snprintf(tmpfile, strlen(file) + 5, "%s.tmp", file) < 3)
- err(EXIT_FAILURE, "snprintf");
-
- umask(0077);
- fp = fopen(tmpfile, "w+");
- if (fp == NULL)
- err(EXIT_FAILURE, "Unable to save store to '%s'", file);
-
- while (cur != NULL) {
- fprintf(fp, "%s %s\n", cur->name, cur->content);
- cur = cur->next;
- }
-
- if (fclose(fp) != 0)
- err(EXIT_FAILURE, "fclose %s", file);
-
- if (rename(tmpfile, file) != 0)
- err(EXIT_FAILURE, "Unable to rename '%s' to '%s'", tmpfile, file);
-}
+#define CMD_EVAL 1
+#define CMD_LIST 2
+#define CMD_RM 3
+#define CMD_SAVE 4
+#define PARAM_LENGTH 256
+#define VALUE_LENGTH 1024
+#define SCAN_FORMAT "%255s %1023[^\n]\n"
-static struct parameter * store_load(char *file) {
- struct parameter *first = NULL;
- struct parameter *new;
+static FILE * store_open(char *file) {
struct stat finfo;
uid_t self_uid = geteuid();
- char vname[128];
- char vcontent[256];
FILE *fp = fopen(file, "r");
/* Assume the store file does not exist and the store is empty
@@ -112,7 +36,7 @@ static struct parameter * store_load(char *file) {
return NULL;
if (fstat(fileno(fp), &finfo) != 0)
- errx(EXIT_FAILURE, "Unable to verify store file permissions (%s)", file);
+ err(EXIT_FAILURE, "Unable to verify store file permissions (%s)", file);
if (finfo.st_uid != self_uid)
errx(EXIT_FAILURE, "Store file '%s' is insecure (must be owned by you, not uid %d)", file, finfo.st_uid);
@@ -120,96 +44,116 @@ static struct parameter * store_load(char *file) {
if ((finfo.st_mode & 077) > 0)
errx(EXIT_FAILURE, "Store file '%s' has insecure permissions %04o (recommended: 0600)", file, finfo.st_mode & 07777);
- while (fscanf(fp, "%127s %255[^\n]\n", vname, vcontent) != EOF) {
- new = malloc(sizeof (struct parameter));
- if (new == NULL)
- err(EXIT_FAILURE, "malloc");
-
- new->name = strdup(vname);
- new->content = strdup(vcontent);
+ return fp;
+}
- if ((new->name == NULL) || (new->content) == NULL)
- err(EXIT_FAILURE, "strdup");
+static char * new_filename(char *file) {
+ char *new_file = malloc(strlen(file) + 5);
- first = list_add(first, new);
- }
+ if (new_file == NULL)
+ err(EXIT_FAILURE, "malloc");
- if (fclose(fp) != 0)
- err(EXIT_FAILURE, "fclose %s", file);
+ if (snprintf(new_file, strlen(file) + 5, "%s.tmp", file) < 3)
+ err(EXIT_FAILURE, "snprintf");
- return first;
+ return new_file;
}
+static FILE * store_open_new(char *file) {
+ FILE *fp;
-static inline void command_clear(char *store_file) {
- /*
- * No error checking - assume that the file didn't exist in the first place
- * if unlink fails.
- */
- unlink(store_file);
+ umask(0077);
+ fp = fopen(file, "w");
+
+ if (fp == NULL)
+ err(EXIT_FAILURE, "fopen %s", file);
+
+ return fp;
}
-static inline void command_eval(char *store_file) {
- struct parameter *first = store_load(store_file);
- struct parameter *cur = first;
- unsigned long int i;
+static inline void print_escaped(char *name, char *content) {
+ unsigned int i;
- while (cur != NULL) {
+ printf("export %s='", name);
- printf("export %s='", cur->name);
- for (i = 0; i < strlen(cur->content); i++) {
- if (cur->content[i] == '\'')
- fputs("'\"'\"'", stdout);
- else
- putchar(cur->content[i]);
- }
- fputs("'\n", stdout);
- cur = cur->next;
+ for (i = 0; i < strlen(content); i++) {
+ if (content[i] == '\'')
+ fputs("'\"'\"'", stdout);
+ else
+ putchar(content[i]);
}
+
+ fputs("'\n", stdout);
}
-static inline void command_list(char *store_file) {
- struct parameter *first = store_load(store_file);
- struct parameter *cur = first;
+static void command_disp(char *file, int command) {
+ char vname[PARAM_LENGTH];
+ char vcontent[VALUE_LENGTH];
+ FILE *fp = store_open(file);
+
+ if (fp == NULL)
+ exit(EXIT_SUCCESS);
- while (cur != NULL) {
- printf("%-15s = %s\n", cur->name, cur->content);
- cur = cur->next;
+ while (fscanf(fp, SCAN_FORMAT, vname, vcontent) != EOF) {
+ if (command == CMD_LIST)
+ printf("%-15s = %s", vname, vcontent);
+ else
+ print_escaped(vname, vcontent);
}
+ if (fclose(fp) != 0)
+ err(EXIT_FAILURE, "fclose %s", file);
}
+static void command_rm_save(char *old_file, char *param, char *value, int argc, int mode) {
+ char curparam[PARAM_LENGTH];
+ char curvalue[VALUE_LENGTH];
+ char *newvalue;
+ char *new_file = new_filename(old_file);
+ FILE *old_fp = store_open(old_file);
+ FILE *new_fp = store_open_new(new_file);
+
+ if (old_fp != NULL) {
+ while (fscanf(old_fp, SCAN_FORMAT, curparam, curvalue) != EOF) {
+ if (strcmp(curparam, param) != 0)
+ if (fprintf(new_fp, "%s %s\n", curparam, curvalue) <= 0)
+ err(EXIT_FAILURE, "fprintf %s", new_file);
+ }
+ if (fclose(old_fp) != 0)
+ err(EXIT_FAILURE, "fclose %s", old_file);
+ }
-static inline void command_rm(char *store_file, char *param) {
- struct parameter *first = store_load(store_file);
- first = list_remove(first, param);
- store_save(first, store_file);
-}
+ if (mode == CMD_SAVE) {
+ if (argc > 3)
+ newvalue = value;
+ else
+ newvalue = getenv(param);
+ if (newvalue == NULL)
+ errx(EXIT_FAILURE, "parameter '%s' has no value", param);
-static inline void command_save(char *store_file, char *param, char *value, int argc) {
- struct parameter *first = store_load(store_file);
- struct parameter new;
- char *newvalue;
- first = list_remove(first, param);
+ if ((strlen(param) > PARAM_LENGTH - 1) || (strlen(newvalue) > VALUE_LENGTH - 1))
+ errx(EXIT_FAILURE, "parameter or value too long (see man envstore -> LIMITATIONS)");
- if (argc > 3)
- newvalue = value;
- else
- newvalue = getenv(param);
+ if (fprintf(new_fp, "%s %s\n", param, newvalue) <= 0)
+ err(EXIT_FAILURE, "fprintf %s", new_file);
+ }
- if (newvalue == NULL)
- errx(EXIT_FAILURE, "parameter '%s' has no value", param);
+ if (fclose(new_fp) != 0)
+ err(EXIT_FAILURE, "fclose %s", new_file);
- if ((strlen(param) > 127) || (strlen(newvalue) > 255))
- errx(EXIT_FAILURE, "parameter or value too long (see man envstore -> LIMITATIONS)");
+ if (rename(new_file, old_file) != 0)
+ err(EXIT_FAILURE, "Unable to rename '%s' to '%s'", new_file, old_file);
+}
- new.name = param;
- new.content = newvalue;
- first = list_add(first, &new);
- store_save(first, store_file);
+static inline void command_clear(char *store_file) {
+ /*
+ * No error checking - assume that the file didn't exist in the first place
+ * if unlink fails.
+ */
+ unlink(store_file);
}
@@ -231,25 +175,26 @@ int main(int argc, char **argv) {
}
}
+
switch (argv[1][0]) {
case 'c':
command_clear(store_file);
break;
case 'e':
- command_eval(store_file);
+ command_disp(store_file, CMD_EVAL);
break;
case 'l':
- command_list(store_file);
+ command_disp(store_file, CMD_LIST);
break;
case 'r':
if (argc < 3)
errx(EXIT_FAILURE, "Usage: rm <parameter>");
- command_rm(store_file, argv[2]);
+ command_rm_save(store_file, argv[2], argv[3], argc, CMD_RM);
break;
case 's':
if (argc < 3)
errx(EXIT_FAILURE, "Usage: save <parameter> [value]");
- command_save(store_file, argv[2], argv[3], argc);
+ command_rm_save(store_file, argv[2], argv[3], argc, CMD_SAVE);
break;
default:
errx(EXIT_FAILURE, "Unknown action: %s", argv[1]);