commit 1782bae59246ceaedd262b6502e47cacc5894db9
parent 72dfecd782b5a99ace6bee35077ce710c07f023e
Author: rlp <rlp@openbsd.localdomain>
Date: Sun, 9 Dec 2018 09:56:43 +0100
add support for OpenBSD
Diffstat:
| M | c/gitoff.c | | | 312 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 312 insertions(+), 0 deletions(-)
diff --git a/c/gitoff.c b/c/gitoff.c
@@ -85,7 +85,9 @@ typedef void (*cmdSetF_t)(gConfig_set_t);
#include <stdio.h>
#include <dirent.h>
#include <libgen.h>
+#if (!__OpenBSD__)
#include <wordexp.h>
+#endif
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
@@ -245,6 +247,7 @@ char* offDEFAULTS[22] = { "/.git/off/objects", "copy", "disable", "offNoValue",
// helpers
//////
+#if (!__OpenBSD__)
// expands ~/
char *expandHome(char *p) {
wordexp_t exp_result;
@@ -259,6 +262,315 @@ char *expandHome(char *p) {
wordfree(&exp_result);
return(p);
}
+#else
+#define and &&
+#define or ||
+#define not !
+#define elif else if
+#define TOKENPASTE2(a, b) a ## b
+#define TOKENPASTE(a, b) TOKENPASTE2(a, b)
+#define UNIQVAR(name) TOKENPASTE(name, __LINE__)
+#define forEachS(list, element) \
+ ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \
+ for (char *element = list[0]; list[UNIQVAR(libsheepyInternalIndex)]!= NULL ; UNIQVAR(libsheepyInternalIndex)++, element = list[UNIQVAR(libsheepyInternalIndex)])
+char *findS(const char *string, const char *needle) {
+
+ // sanity checks
+ if (!string || !needle) {
+ return(NULL);
+ }
+ return(strstr(string, needle));
+}
+char *strLCpy(char *dst, size_t dstSize, const char *src) {
+
+ if (!dst || !src) {
+ return(NULL);
+ }
+
+ char *r = strncpy(dst, src, dstSize);;
+ if (dstSize) {
+ r[dstSize-1] = 0;
+ }
+ return(r);
+}
+char *strLNCat(char *dst, size_t dstSize, const char *src, size_t srcLen) {
+
+ if (!dst || !src) {
+ return(NULL);
+ }
+
+ size_t dL = strnlen(dst, dstSize);
+ size_t dstLen = dstSize-1;
+
+ if (dL >= dstLen) {
+ // buffer is full
+ return(dst);
+ }
+
+ size_t sL = strnlen(src, srcLen);
+
+ if (dL+sL > dstLen) {
+ // truncate
+ return(strncat(dst, src, dstLen - dL));
+ }
+ else {
+ return(strncat(dst, src, srcLen));
+}
+ }
+#define forEachCharP(list, element) \
+ for (char **element=list ; *element != NULL ; element++)
+size_t listLengthS(char **list) {
+ size_t r = 0;;
+
+ // sanity checks
+ if (!list) {
+ return(0);
+ }
+ forEachCharP(list, i) {
+ r++;
+ }
+ return(r);
+}
+char **listPushS(char ***list, const char *s) {
+
+ // sanity checks
+ if (!list) {
+ return(NULL);
+ }
+
+ if (!*list) {
+ *list = malloc(2 * sizeof(char *));
+ if (!s) {
+ (*list)[0] = NULL;
+ }
+ else {
+ (*list)[0] = strdup(s);
+ }
+ (*list)[1] = NULL;
+ }
+ else {
+ // realloc list and copy s to last element
+ size_t len;
+ len = listLengthS(*list);
+ char **tmp = realloc(*list, (len+2) * sizeof(char *));
+ if (!tmp) {
+ return(NULL);
+ }
+ else {
+ *list = tmp;
+ (*list)[len+1] = NULL;
+ if (!s) {
+ // s is NULL, add NULL in list
+ (*list)[len] = NULL;
+ }
+ else {
+ (*list)[len] = strdup(s);
+ }
+ }
+ }
+ return(*list);
+}
+#define listEmptyS(list) \
+ do {\
+ list = malloc(1 * sizeof(char *)); \
+ if (list) list[0] = NULL; \
+ } while(0);
+char **readText(const char *filePath) {
+ FILE *fp = NULL;
+ size_t len;
+ char* line = NULL;
+ ssize_t read;
+ char **list = NULL;
+
+ // sanity checks
+ if (!filePath) {
+ return(NULL);
+ }
+ fp = fopen(filePath, "r");
+ if (!fp) {
+ //pFuncError
+ //shEPrintfS("The path was: \"%s\"\n", filePath);
+ return(NULL);
+ }
+ // read all lines
+ read = getline(&line, &len, fp);
+ while (read != -1) {
+ {
+ char* pos = NULL;
+ pos = strchr(line, '\n');
+ if (pos != NULL)
+ *pos = '\0';
+ }
+ listPushS(&list, line);
+ read = getline(&line, &len, fp);
+ }
+ fclose(fp);
+ free(line);
+ if (!list) {
+ // nothing was read
+ listEmptyS(list);
+ }
+ return(list);
+}
+bool startsWithS(const char *string1, const char *string2) {
+
+ // sanity checks
+ if (!string1 || !string2) {
+ return(false);
+ }
+ return(strncmp(string1, string2, strlen(string2)) == 0);;
+}
+void listFreeS(char **list) {
+
+ // sanity checks
+ if (list) {
+ forEachCharP(list, e) {
+ free(*e);
+ }
+ free(list);
+}
+ }
+char *iAppendS(char **string1, const char *string2) {
+ char *tmp = NULL;
+ size_t l1;
+ size_t l2;
+
+ if (!string1 || !string2) {
+ return(NULL);
+ }
+
+ if (!*string1) {
+ *string1 = strdup(string2);
+ return(*string1);
+ }
+
+ l1 = strlen(*string1);
+ l2 = strlen(string2);
+
+ if (!l2) {
+ // empty string
+ return(*string1);
+ }
+
+ tmp = realloc(*string1, l1 + l2 + 1);
+ if (!tmp) {
+ return(NULL);
+ }
+
+ *string1 = tmp;
+ strcat(*string1, string2);
+ return(*string1);
+}
+char *expandHome(char *path) {
+
+ // sanity checks
+ if (!path) {
+ return(NULL);
+ }
+
+
+ if (path[0] == 0) {
+ // path is empty
+ return(path);
+ }
+
+ // steps
+ // determine path format
+ // set user name, either current user or user name in path
+ // add : at the end of username to match line in the /etc/passwd file
+ // find home path in the passwd file
+
+ enum {noExpand, currentUser, otherUser};
+
+ // determine path format
+ int status = noExpand;
+ if (path[0] == '~' and (path[1] == '/' or path[1] == 0)) {
+ // path="~/..."
+ status = currentUser;
+ }
+ elif (path[0] == '~' and path[1] != '/') {
+ // path="~USER..."
+ status = otherUser;
+ }
+
+ // there is no tilde to expand, return path unchanged
+ if (status == noExpand) {
+ return(path);
+ }
+
+ // set user name, either current user or user name in path
+ char user[33] = {0};
+ size_t pathStart = 0;
+
+ if (status == currentUser) {
+ // use getlogin to find current username
+ // sizeof(user)-1 to keep a char tp append final ':'
+ if (getlogin_r(user, sizeof(user)-1)) {
+ // error
+ //logE("getlogin for current user");
+ } {
+ pathStart = 1;
+ }
+ }
+ else {
+ // username is in path
+ // from index 1 (skip ~) to the first /
+ char *slash = findS(path, "/");
+ if (!slash) {
+ // no slash found, path is in the form: ~USER
+ // copy string after ~ to the end of the string
+ strLCpy(user, sizeof(user)-1, path+1);
+ pathStart = strlen(path);
+ }
+ else {
+ // copy string after ~ to first slash
+ pathStart = slash - path;
+ strLNCat(user, sizeof(user)-1, path+1, pathStart-1);
+ }
+ }
+
+ // add : at the end of username to match line in passwd
+ size_t len = strlen(user);
+ user[len] = ':';
+ user[len+1] = 0;
+
+
+ // find home path in the passwd file
+ char **pwd = readText("/etc/passwd");
+
+ if (!pwd) {
+ return(NULL);
+ }
+
+ // result
+ char *r = NULL;
+
+ forEachS(pwd, l) {
+ if (startsWithS(l, user)) {
+ // found the user
+ char **l_l = split(l, ":");
+ // copy home path to result
+ r = strdup(l_l[5]);
+ listFreeS(l_l);
+ break;
+ }
+ }
+
+ listFreeS(pwd);
+
+ if (!r) {
+ // user not found in this system
+ return(NULL);
+ }
+
+ // append rest of the path to the result
+ iAppendS(&r, path + pathStart);
+
+ free(path);
+
+ return(r);
+}
+#endif
// appends log to git config off.log