Jessie,

I made some corrections, added comments in the code, and deleted
comments that might be present at the beginning of the .tab files.
The function which interprets the lines, is the same as for the inittab file.
The idea is to have one file per service to start without having to
touch the inittab file.

All changes: init.c paths.h and Makefile are in a single .patch file.

PS: I no longer receive your emails in my mailbox, is there a setting
to receive them?

Didier

Le jeu. 2 janv. 2020 à 08:25, Didier Gaudin <didier.gau...@gmail.com> a écrit :
>
> Hello,
> Happy new year!
> I send you my patch to add /etc/inttab.d support.
>
> The patch scan the /etc/inittab.d/ and read only the first line of *.tab 
> files.
> Can you give me your feed-back about this patch.
>
> Didier.
>
>
> Le mer. 25 déc. 2019 à 09:50, Petter Reinholdtsen <p...@hungry.com> a écrit :
> >
> >
> > Hello, and Merry Christmas. :)
> >
> > [Didier.Gaudin]
> > > do you think it is possible, to have a directory /etc/inittab.d in
> > > addition to the /etc/inittab to add service : 1 custom service per file
> > > ?
> >
> > I believe it is both possible and an advantage. :)  Perhaps you can
> > create a patch to do so?
> >
> > --
> > Happy hacking
> > Petter REinholdtsen
diff -Naur sysvinit.orig/src/init.c sysvinit.new/src/init.c
--- sysvinit.orig/src/init.c	2019-12-31 19:09:12.687989710 +0100
+++ sysvinit.new/src/init.c	2020-01-03 19:13:30.049986234 +0100
@@ -63,6 +63,11 @@
 #include <sys/ttydefaults.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
+/*
+ * inittab.d
+ */
+#include <sys/types.h>
+#include <dirent.h>
 
 #ifdef WITH_SELINUX
 #  include <selinux/selinux.h>
@@ -1431,6 +1436,7 @@
 void read_inittab(void)
 {
   FILE		*fp;			/* The INITTAB file */
+  FILE		*fp_tab;		/* The INITTABD files */
   CHILD		*ch, *old, *i;		/* Pointers to CHILD structure */
   CHILD		*head = NULL;		/* Head of linked list */
 #ifdef INITLVL
@@ -1448,7 +1454,10 @@
   int		round;			/* round 0 for SIGTERM, 1 for SIGKILL */
   int		foundOne = 0;		/* No killing no sleep */
   int		talk;			/* Talk to the user */
-  int		done = 0;		/* Ready yet? */
+  int		done = -1;		/* Ready yet? , 2 level : -1 nothing done, 0 inittab done, 1 inittab and inittab.d done */
+  DIR 		*tabdir=NULL;		/* the INITTAB.D dir */
+  struct dirent *file_entry;		/* inittab.d entry */
+  char 		f_name[272];		/* size d_name + strlen /etc/inittad.d/ */
 
 #if DEBUG
   if (newFamily != NULL) {
@@ -1464,22 +1473,73 @@
   if ((fp = fopen(INITTAB, "r")) == NULL)
 	initlog(L_VB, "No inittab file found");
 
-  while(!done) {
+  /*
+   *  Open INITTAB.D directory 
+   */
+  if( (tabdir = opendir(INITTABD))==NULL)
+	  initlog(L_VB, "No inittab.d directory found");
+
+  while(done!=1) {
 	/*
 	 *	Add single user shell entry at the end.
 	 */
-	if (fp == NULL || fgets(buf, sizeof(buf), fp) == NULL) {
-		done = 1;
-		/*
-		 *	See if we have a single user entry.
-		 */
-		for(old = newFamily; old; old = old->next)
-			if (strpbrk(old->rlevel, "S")) break;
-		if (old == NULL)
-			snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SULOGIN);
-		else
+	if(done == -1) {
+		if (fp == NULL || fgets(buf, sizeof(buf), fp) == NULL) {
+			done = 0;
+			/*
+			 *	See if we have a single user entry.
+			 */
+			for(old = newFamily; old; old = old->next)
+				if (strpbrk(old->rlevel, "S"))  break;
+			if (old == NULL)
+				snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SULOGIN);
+			else
+				continue;
+		}
+	} /* end if( done==-1) */
+	else if ( done == 0 ){
+		/* parse /etc/inittab.d and read all .tab files */
+		if(tabdir!=NULL){
+			if( (file_entry = readdir(tabdir))!=NULL){
+				/* ignore files not like *.tab */
+				if (!strcmp(file_entry->d_name, ".") || !strcmp(file_entry->d_name, ".."))
+					continue;
+				if (strlen(file_entry->d_name) < 5 || strcmp(file_entry->d_name + strlen(file_entry->d_name) - 4, ".tab"))
+					continue;
+				/*
+				 * initialize filename
+				 */
+				memset(f_name,0,sizeof(char)*272);
+				snprintf(f_name,272,"/etc/inittab.d/%s",file_entry->d_name);
+				initlog(L_VB, "Reading: %s",f_name);
+				/*
+				 * read file in inittab.d only one entry per file
+				 */
+				if ((fp_tab = fopen(f_name, "r")) == NULL)
+					continue;
+				/* read the file while the line contain comment */
+				while( fgets(buf, sizeof(buf), fp_tab) != NULL) {
+					for(p = buf; *p == ' ' || *p == '\t'; p++);
+					if (*p != '#' && *p != '\n')
+						break;
+				}
+				fclose(fp_tab);
+				/* do some checks */
+				if( buf == NULL ) 
+					continue;
+				if( strlen( p  ) == 0 )
+					continue;
+			} /* end of readdir, all is done */
+			else { 
+				done = 1;
+				continue;
+			}
+		} /* end of if(tabdir!=NULL) */
+		else {
+			done = 1;
 			continue;
-	}
+		}
+	} /* end of if ( done == 0 ) */
 	lineNo++;
 	/*
 	 *	Skip comments and empty lines
@@ -1630,10 +1690,12 @@
 			break;
 		}
   }
+
   /*
    *	We're done.
    */
   if (fp) fclose(fp);
+  if(tabdir) closedir(tabdir);
 
 #ifdef __linux__
   check_kernel_console();
diff -Naur sysvinit.orig/src/Makefile sysvinit.new/src/Makefile
--- sysvinit.orig/src/Makefile	2019-12-31 19:09:12.729989709 +0100
+++ sysvinit.new/src/Makefile	2020-01-03 19:10:19.935994068 +0100
@@ -202,6 +202,7 @@
 			$(INSTALL_EXEC) $$i $(ROOT)/usr/bin/ ; \
 		done
 		# $(INSTALL_DIR) $(ROOT)/etc/
+		$(INSTALL_DIR) $(ROOT)/etc/inittab.d
 		# $(INSTALL_EXEC) ../doc/initscript.sample $(ROOT)/etc/
 		ln -sf halt $(ROOT)/sbin/reboot
 		ln -sf halt $(ROOT)/sbin/poweroff
diff -Naur sysvinit.orig/src/paths.h sysvinit.new/src/paths.h
--- sysvinit.orig/src/paths.h	2019-12-31 19:09:12.734989708 +0100
+++ sysvinit.new/src/paths.h	2020-01-03 19:09:26.134996285 +0100
@@ -27,6 +27,7 @@
 #define SECURETTY	"/etc/securetty"	/* List of root terminals */
 #define SDALLOW		"/etc/shutdown.allow"	/* Users allowed to shutdown */
 #define INITTAB		"/etc/inittab"		/* Location of inittab */
+#define INITTABD	"/etc/inittab.d"	/* Location of inittab.d directory */
 #define INIT		"/sbin/init"		/* Location of init itself. */
 #define NOLOGIN		"/etc/nologin"		/* Stop user logging in. */
 #define FASTBOOT	"/fastboot"		/* Enable fast boot. */

Reply via email to