From 99d44f1b4892f86714a9eff18eee5267be56df7c Mon Sep 17 00:00:00 2001
From: obarun <eric@obarun.org>
Date: Fri, 21 Jun 2019 16:51:25 +1100
Subject: [PATCH] pass to oblibs library

---
 doc/execl-envfile.html          | 19 ++++----
 src/extra-tools/execl-envfile.c | 77 +++++++++++++++++++++++++++------
 2 files changed, 75 insertions(+), 21 deletions(-)

diff --git a/doc/execl-envfile.html b/doc/execl-envfile.html
index bab78488..f520de6d 100644
--- a/doc/execl-envfile.html
+++ b/doc/execl-envfile.html
@@ -25,11 +25,11 @@
 
 <h2> Interface </h2>
 	<pre>
-	execl-envfile [ -h ] [ -f <em>file</em> ] [ -l ] <em>dir</em> <em>prog</em>
+	execl-envfile [ -h ] [ -l ] <em>src</em> <em>prog</em>
 	</pre>
 
 	<p>
-      This tool expects to find a regular file(s) in <em>dir</em> containing one or multiple <tt>key=value</tt> pair. For each files found:  it will parse the file, import the <tt>key=value</tt> then execs <em>prog</em> with the modified environment.
+      This tool expects to find a regular file(s) or directory as <em>src</em> containing one or multiple <tt>key=value</tt> pair. For each files found:  it will parse the file, import the <tt>key=value</tt> then execs <em>prog</em> with the modified environment.
     </p>
 	<ul>
 		<li>It opens and reads the file.</li>
@@ -39,21 +39,22 @@
 		<li>It unexports the variable if requested.</li>
 		<li>It execs <em>prog</em> with the modified environment.</li>
 	</ul>
+	<p>In case as <em>src</em> is a directory, the same processus is made for each files found in <em>src</em>. <em>src</em> can be absolute or relative path. In case of relative path only <tt>'../'</tt>,<tt>'./'</tt>, <tt>'.'</tt> or <tt>'..'</tt> are accepted as valid format.</p>
 <h2> Options </h2>
 
 	<ul>
 		<li> <tt>-h&nbsp;</tt>&nbsp;: prints this help. </li>
 		<li>
-			<tt>-f&nbsp;<em>file</em>&nbsp;</tt>&nbsp;: only parses the <em>file</em> found in <em>dir</em>.
+			<tt>-f&nbsp;<em>file</em>&nbsp;</tt>&nbsp;: only parses the <em>file</em> found in <em>src</em>.<strong>deprecated</strong>
 		</li>
 		<li>
-			<tt>-l&nbsp;</tt>&nbsp;: loose. does nothing and executes <em>prog</em> directly if <em>dir</em> does not contain any regular file(s) or <em>dir</em> doesn't exist.
+			<tt>-l&nbsp;</tt>&nbsp;: loose. does nothing and executes <em>prog</em> directly if <em>src</em> does not contain any regular file(s) or <em>src</em> doesn't exist.
 		</li>
 		
 	</ul>
 
-<h2> File syntax </h2>
-	<p><em>file</em> is a text file containing lines of the form <tt>key = value</tt>. Whitespace is permitted before and after <em>key</em>, and before or after <em>value</em>,
+<h2> <em>File</em> syntax </h2>
+	<p><em>file</em> is a text file containing lines of the form <tt>key=value</tt>. Whitespace is permitted before and after <em>key</em>, and before or after <em>value</em>,
 	Quoting is also possible. In this case, the quoting field is treated as one word.
 	</p>
 	<p>Empty lines, or lines containing only whitespace, are ignored. Lines beginning with <tt>#</tt> (possibly after some whitespace) are ignored (and typically used for comments). Comments are <strong>not</strong> possible at the end of lines:
@@ -61,11 +62,13 @@
 	</p>
 	<p>Empty <em>value</em> is <strong>not</strong> permitted.</p>
 	<p>If <tt>key</tt> begin by a <tt>'!'</tt> character: <tt>!key=value</tt> the <tt>key</tt> will be removed from the environment after the substitution.</p>
+	<p>If the same <tt>key=value</tt> pair is found multiple time, only the first one definition is keepts.</p>
+	<p>It must be terminated by an <strong>empty new line</strong>.</p>
 <h2> Example of use </h2>
 	<pre>
 	#!/usr/bin/execlineb -P
 	fdmove -c 2 1
-	execl-envfile -f ntpd /etc/66/conf/
+	execl-envfile /etc/66/conf/ntpd
 	foreground { mkdir -p  -m 0755 ${RUNDIR} } 
 	execl-cmdline -s { ntpd ${CMD_ARGS} }
 	</pre>
@@ -82,6 +85,6 @@
 	</pre>
 	<p>where <tt>/etc/66/conf</tt> directory contains two named files <tt>RUNDIR</tt> and <tt>CMD_ARGS</tt> written with <tt>/run/openntpd</tt> and <tt>-d -s</tt> respectively.</p>
 <h2> limits</h2>
-<p><em>dir</em> cannot exceed more than 100 files. Each file cannot contain more than 4095 bytes or more than 50 <em>key=value</em> pairs.</p>
+<p><em>src</em> cannot exceed more than 100 files. Each file cannot contain more than 4095 bytes or more than 50 <em>key=value</em> pairs.</p>
 </body>
 </html>
diff --git a/src/extra-tools/execl-envfile.c b/src/extra-tools/execl-envfile.c
index ea6ec4a7..f9f4b499 100644
--- a/src/extra-tools/execl-envfile.c
+++ b/src/extra-tools/execl-envfile.c
@@ -15,10 +15,12 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #include <oblibs/string.h>
 #include <oblibs/stralist.h>
 #include <oblibs/error2.h>
+#include <oblibs/types.h>
 #include <oblibs/obgetopt.h>
 #include <oblibs/directory.h>
 #include <oblibs/files.h>
@@ -37,20 +39,19 @@
 #include <66/parser.h>
 #include <66/environ.h>
 
-unsigned int VERBOSITY = 1 ;
 static stralloc SAENV = STRALLOC_ZERO ;
 static genalloc GAENV = GENALLOC_ZERO ; //diuint32, pos in senv
 
-#define USAGE "execl-envfile [ -h help ] [ -f file ] [ -l ] dir prog"
+#define USAGE "execl-envfile [ -h help ] [ -l ] src prog"
 
 static inline void info_help (void)
 {
   static char const *help =
-"execl-envfile <options> dir prog\n"
+"execl-envfile <options> src prog\n"
 "\n"
 "options :\n"
 "	-h: print this help\n" 
-"	-f: file to parse\n"
+"	-f: file to parse(deprecated)\n"
 "	-l: loose\n"
 ;
 
@@ -58,14 +59,24 @@ static inline void info_help (void)
     strerr_diefu1sys(111, "write to stdout") ;
 }
 
+int loop_stra(stralloc *sa,char const *search)
+{
+	size_t i = 0, len = sa->len ;
+	for (;i < len; i += strlen(sa->s + i) + 1)
+		if (!strcmp(sa->s+i,search)) return 1 ;
+	
+	return 0 ;
+}
+
 int main (int argc, char const *const *argv, char const *const *envp)
 {
-	int r, i, one, unexport  ;
+	int r, i, unexport  ;
 	int insist = 1 ;
-	
+	size_t pathlen ;
 	char const *path = 0 ;
 	char const *file = 0 ;
-	
+	char tpath[MAXENV + 1] ;
+	char tfile[MAXENV+1] ;
 	stralloc src = STRALLOC_ZERO ;
 	stralloc modifs = STRALLOC_ZERO ;
 	stralloc dst = STRALLOC_ZERO ;
@@ -73,7 +84,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
 	
 	exlsn_t info = EXLSN_ZERO ;
 	
-	r = i = one = unexport = 0 ;
+	r = i = unexport = 0 ;
 	insist = 1 ;
 	
 	PROG = "execl-envfile" ;
@@ -88,7 +99,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
 			switch (opt)
 			{
 				case 'h' : 	info_help(); return 0 ;
-				case 'f' :  file = l.arg ; one = 1 ; break ;
+				case 'f' :  file = l.arg ;  break ;
 				case 'l' : 	insist = 0 ; break ;
 				default : exitusage(USAGE) ; 
 			}
@@ -101,7 +112,44 @@ int main (int argc, char const *const *argv, char const *const *envp)
 	path = *argv ;
 	argv++;
 	argc--;
-	if (path[0] != '/') strerr_dief3x(111,"directory: ",path," must be an absolute path") ;
+	
+	/** Mark -f as deprecated */	
+	if (file)
+	{
+		strerr_warnw1x("-f options is deprecated") ;
+		if (path[0] != '/') strerr_dief3x(111,"path of: ",path,": must be absolute") ;
+	}
+	else
+	{
+		r = scan_mode(path,S_IFREG) ;
+		if (!r) strerr_diefu2sys(111,"find: ",path) ;
+		if (r < 0)
+		{
+			r = scan_mode(path,S_IFDIR) ;
+			if (!r) strerr_diefu2sys(111,"find: ",path) ;
+			if (r < 0) strerr_dief2x(111,"invalid format of: ", path) ;
+			if (path[0] == '.')
+			{
+				if (!dir_beabsolute(tpath,path)) 
+					strerr_diefu2sys(111,"find absolute path of: ",path) ;
+			}
+			else if (path[0] != '/') strerr_dief3x(111,"path of: ",path,": must be absolute") ;
+			else
+			{
+				pathlen = strlen(path) ;
+				memcpy(tpath,path,pathlen);
+				tpath[pathlen] = 0 ;
+			}
+			path = tpath ;
+		}
+		else
+		{
+			if (!basename(tfile,path)) strerr_diefu2x(111,"get file name of: ",path) ;
+			file = tfile ;
+			if (!dirname(tpath,path)) strerr_diefu2x(111,"get parent path of: ",path) ;
+			path = tpath ;
+		}
+	}
 	
 	r = dir_get(&toparse,path,"",S_IFREG) ;
 	if (!r && insist) strerr_diefu2sys(111,"get file from: ",path) ;
@@ -110,7 +158,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
 		xpathexec_run(argv[0],argv,envp) ;
 	}
 	
-	if (one)
+	if (file)
 	{
 		r = stra_findidx(&toparse,file) ;
 		if (r < 0) 
@@ -130,10 +178,12 @@ int main (int argc, char const *const *argv, char const *const *envp)
 		for (i = 0 ; i < genalloc_len(stralist,&toparse) ; i++)
 		{
 			src.len = 0 ;
+			size_t n = i + MAXVAR ;
 			if (i > MAXFILE) strerr_dief2x(111,"to many file to parse in: ",path) ;
 			if (!file_readputsa(&src,path,gaistr(&toparse,i))) strerr_diefu4sys(111,"read file: ",path,"/",gaistr(&toparse,i)) ;
 			if (!env_parsenclean(&modifs,&src)) strerr_diefu4x(111,"parse and clean environment of: ",path,"/",gaistr(&toparse,i)) ;
 			if (!env_split(&GAENV,&SAENV,&src)) strerr_diefu4x(111,"split environment of: ",path,"/",gaistr(&toparse,i)) ;
+			if (genalloc_len(stralist,&toparse) > n) strerr_dief4x(111,"to many variables in file: ",path,"/",gaistr(&toparse,i)) ;
 		}
 	}
 	genalloc_deepfree(stralist,&toparse,stra_free) ;
@@ -151,7 +201,6 @@ int main (int argc, char const *const *argv, char const *const *envp)
 	
 	for (i = 0 ; i < genalloc_len(diuint32,&GAENV) ; i++)
 	{
-			if (i > MAXVAR) strerr_dief1x(111,"to many variables") ;
 			unexport = 0 ;
 			int key = genalloc_s(diuint32,&GAENV)[i].left ;
 			int val = genalloc_s(diuint32,&GAENV)[i].right ;
@@ -160,7 +209,9 @@ int main (int argc, char const *const *argv, char const *const *envp)
 				key++ ;
 				unexport = 1 ;
 			}
-			if (!env_substitute(SAENV.s + key,SAENV.s + val,&info,newenv,unexport)) strerr_diefu4x(111,"substitute value of: ",SAENV.s + key," by: ",SAENV.s + val) ;
+			if(!loop_stra(&info.vars,SAENV.s + key))
+				if (!env_substitute(SAENV.s + key,SAENV.s + val,&info,newenv,unexport)) 
+					strerr_diefu4x(111,"substitute value of: ",SAENV.s + key," by: ",SAENV.s + val) ;
 	}
 	genalloc_free(diuint32,&GAENV) ;
 	stralloc_free(&SAENV) ;
-- 
GitLab