aboutsummaryrefslogtreecommitdiff
path: root/libiot/sys/history.c
diff options
context:
space:
mode:
authorbhgv <bhgv.empire@gmail.com>2020-05-10 02:59:23 +0300
committerbhgv <bhgv.empire@gmail.com>2020-05-10 02:59:23 +0300
commit31b4edc67b75658ce5e2d41f2fc87331f4b26d49 (patch)
treea7b6ea659fe62e0a7239f29170024f524595fb4d /libiot/sys/history.c
parentc76314f0f38f4ed028610a6db4452879a556b35f (diff)
a try to add support of FreeRTOS riscV-64 (k210 cpu). first step
Diffstat (limited to 'libiot/sys/history.c')
-rw-r--r--libiot/sys/history.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/libiot/sys/history.c b/libiot/sys/history.c
new file mode 100644
index 0000000..e01e767
--- /dev/null
+++ b/libiot/sys/history.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2015 - 2018, IBEROXARXA SERVICIOS INTEGRALES, S.L.
+ * Copyright (C) 2015 - 2018, Jaume Olivé Petrus (jolive@whitecatboard.org)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * * The WHITECAT logotype cannot be changed, you can remove it, but you
+ * cannot change it in any way. The WHITECAT logotype is:
+ *
+ * /\ /\
+ * / \_____/ \
+ * /_____________\
+ * W H I T E C A T
+ *
+ * * Redistributions in binary form must retain all copyright notices printed
+ * to any local or remote output device. This include any reference to
+ * Lua RTOS, whitecatboard.org, Lua, and other copyright notices that may
+ * appear in the future.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 <COPYRIGHT HOLDER> 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.
+ *
+ * Lua RTOS, shell history functions
+ *
+ */
+
+#include "history.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <sys/tail.h>
+#include <sys/mount.h>
+#include <sys/status.h>
+#include <sys/path.h>
+
+static void history_add_internal(const char *buf) {
+ // Get the history file name
+ char fname[PATH_MAX + 1];
+ if (!mount_history_file(fname, sizeof(fname))) {
+ return;
+ }
+
+ int retries = 0;
+
+again: {
+ // Open the history file
+ FILE *fp = fopen(fname,"a");
+ if (!fp) {
+ // File not found, try to create it, and open again
+ mkfile(fname);
+ fp = fopen(fname,"a");
+ if (!fp) {
+ return;
+ }
+ }
+
+ // Get file size
+ long size;
+
+ if ((size = ftell(fp)) < 0) {
+ fclose(fp);
+ return;
+ }
+
+ // Write to history file
+ int len = strlen(buf);
+
+ int no_space = 0;
+
+ if (fwrite(buf, 1, len, fp) != len) {
+ no_space = (errno == ENOSPC);
+ }
+
+ if (!no_space) {
+ if (fflush(fp) == EOF) {
+ no_space = (errno == ENOSPC);
+ }
+ }
+
+ if (no_space) {
+ // Truncate file to the original size
+ if (ftruncate(fileno(fp), size) < 0) {
+ fclose(fp);
+ return;
+ }
+
+ if (retries == 0) {
+ // Tail file
+ fclose(fp);
+ file_tails(fname, fp->_blksize);
+
+ retries++;
+ goto again;
+ }
+ }
+
+ fclose(fp);
+ }
+}
+
+void history_add(const char *line) {
+ history_add_internal("\n");
+ history_add_internal(line);
+}
+
+int history_get(int index, int up, char *buf, int buflen) {
+ // Get the history file name
+ char fname[PATH_MAX + 1];
+ if (!mount_history_file(fname, sizeof(fname))) {
+ return -2;
+ }
+
+ // Open history file
+ FILE *fp = fopen(fname,"r");
+ if (!fp) {
+ // File not found, try to create it, and open again
+ mkfile(fname);
+ fp = fopen(fname,"r");
+ if (!fp) {
+ return -2;
+ }
+ }
+
+ int pos, len, new_pos;
+ char c;
+
+ if (index == -1) {
+ fseek(fp, 0, SEEK_END);
+ pos = ftell(fp);
+ } else {
+ pos = index;
+ }
+
+ if ((pos == 0) && (up)) {
+ fclose(fp);
+ return -3;
+ }
+
+ new_pos = pos;
+
+ while ((pos >= 0) && !feof(fp)) {
+ if (up)
+ fseek(fp, --pos, SEEK_SET);
+ else
+ fseek(fp, ++pos, SEEK_SET);
+
+ c = fgetc(fp);
+ if (c == '\n') {
+ break;
+ }
+ }
+
+ new_pos = pos;
+
+ if ((pos >= 0) && !feof(fp)) {
+ // Get line
+ fgets(buf, buflen, fp);
+ len = strlen(buf);
+
+ // Strip \r \n chars at the end, if present
+ while ((buf[len - 1] == '\r') || (buf[len - 1] == '\n')) {
+ len--;
+ }
+
+ buf[len] = '\0';
+ } else {
+ if (feof(fp))
+ new_pos = -1;
+ else
+ new_pos = 0;
+
+ buf[0] = 0;
+ }
+
+ fclose(fp);
+
+ return new_pos;
+}