@@ -555,6 +555,22 @@ rc_runlevel_stacks(const char *runlevel)
555555 return stack ;
556556}
557557
558+ static const char * config_path [] = {
559+ RC_SYSCONFDIR "/rc" ,
560+ RC_SYSCONFDIR ,
561+ #ifdef RC_LOCAL_PREFIX
562+ RC_LOCAL_PREFIX "/etc/rc" ,
563+ RC_LOCAL_PREFIX "/etc" ,
564+ #endif
565+ #ifdef RC_PKG_PREFIX
566+ RC_PKG_PREFIX "/etc/rc" ,
567+ RC_PKG_PREFIX "/etc" ,
568+ #endif
569+ RC_LIBEXECDIR ,
570+ RC_SVCDIR ,
571+ NULL ,
572+ };
573+
558574static struct {
559575 bool set ;
560576 char * svcdir , * confdir , * runleveldir ;
@@ -564,7 +580,7 @@ static struct {
564580 char * buffer ;
565581 size_t count ;
566582 int * fds ;
567- const char * * entries ;
583+ const char * * entries , * * allocd ;
568584} rc_path ;
569585
570586static void
@@ -574,108 +590,130 @@ free_rc_dirs(void)
574590 X (rc_dirs .svcdir );
575591 X (rc_dirs .confdir );
576592 X (rc_dirs .runleveldir );
577-
593+ X ( rc_path . allocd );
578594 X (rc_path .buffer );
579- X (rc_path .entries );
580595 X (rc_path .fds );
581596#undef X
582597}
583598
584- static inline size_t
585- append_path (FILE * buf , int path_len , const char path [static path_len ], const char * suffix )
599+ __attribute__((__format__ (__printf__ , 2 , 3 )))
600+ static void
601+ append_path (FILE * fp , const char * fmt , ...)
586602{
587- fprintf (buf , "%.*s%s%c" , path_len , path , suffix ? suffix : "" , '\0' );
588- return 1 ;
603+ va_list va ;
604+
605+ va_start (va , fmt );
606+ vfprintf (fp , fmt , va );
607+ fputc ('\0' , fp );
608+ va_end (va );
609+
610+ rc_path .count ++ ;
589611}
590612
591- static size_t
592- append_path_string ( FILE * buf , const char * path , const char * suffix )
613+ static const char *
614+ strnsep ( const char * * str , size_t * size , const char sep )
593615{
594- size_t count = 0 ;
616+ const char * ret = * str ;
595617
596- for ( const char * entry = path ; ( path = strchrnul ( entry , ':' )); entry = path + 1 ) {
597- size_t entry_len = path - entry ;
618+ if (! ret )
619+ return NULL ;
598620
599- if (! entry_len )
600- continue ;
601- count += append_path ( buf , entry_len , entry , suffix );
602- if (! * path )
603- break ;
604- }
621+ * str = strchrnul ( ret , sep );
622+ * size = * str - ret ;
623+ if (! * * str )
624+ * str = NULL ;
625+ else
626+ * str += 1 ;
605627
606- return count ;
628+ return ret ;
607629}
608630
609- static inline size_t
610- append_path_xdg ( FILE * buf , const char * home , const char * dirs , const char * fallback , bool user )
631+ static const char *
632+ strnullsep ( const char * * str , size_t * size )
611633{
612- const char * path ;
613- size_t count = 0 ;
634+ const char * ret = * str ;
635+ size_t len ;
636+
637+ if (!ret )
638+ return NULL ;
639+
640+ len = strnlen (ret , * size - 1 ) + 1 ;
614641
615- if (!(path = getenv (dirs )))
616- path = fallback ;
642+ if ((* size -= len ))
643+ * str += len ;
644+ else
645+ * str = NULL ;
617646
618- if (home )
619- count += append_path (buf , strlen (home ), home , NULL );
620- return count + append_path_string (buf , path , user ? "/rc/user" : "/rc" );
647+ return ret ;
621648}
622649
623- static inline size_t
624- append_path_array (FILE * buf , size_t path_len , const char * * path , bool user )
650+ static void
651+ append_user_path (FILE * fp )
625652{
626- size_t count = 0 ;
627- while (count < path_len ) {
628- const char * entry = path [count ++ ];
629- append_path (buf , strlen (entry ), entry , user ? "/user" : "" );
630- }
631- return count ;
653+ const char * xdg , * entry ;
654+ size_t size ;
655+
656+ append_path (fp , "%s" , rc_dirs .confdir );
657+ if (!(xdg = getenv ("XDG_CONFIG_DIRS" )))
658+ append_path (fp , "/etc/xdg/rc" );
659+ else while ((entry = strnsep (& xdg , & size , ':' )))
660+ if (size ) append_path (fp , "%.*s/rc" , (int ) size , entry );
661+
662+ for (size_t i = 0 ; i < ARRAY_SIZE (config_path ) - 2 ; i ++ )
663+ append_path (fp , "%s/user" , config_path [i ]);
664+ append_path (fp , "%s" , rc_dirs .svcdir );
632665}
633666
634667static void
635- load_dynamic_path ( bool user )
668+ append_rc_path ( FILE * fp , const char * path , bool user )
636669{
637- static const char * config_path [] = {
638- RC_SYSCONFDIR "/rc" ,
639- RC_SYSCONFDIR ,
640- #ifdef RC_LOCAL_PREFIX
641- RC_LOCAL_PREFIX "/etc/rc" ,
642- RC_LOCAL_PREFIX "/etc" ,
643- #endif
644- #ifdef RC_PKG_PREFIX
645- RC_PKG_PREFIX "/etc/rc" ,
646- RC_PKG_PREFIX "/etc" ,
647- #endif
648- RC_LIBEXECDIR ,
649- };
650-
651- const char * path ;
670+ bool has_user = false;
671+ const char * entry ;
652672 size_t size ;
653- FILE * fp = xopen_memstream (& rc_path .buffer , & size );
654-
655- rc_path .count = 0 ;
656- if ((path = getenv ("RC_PATH" ))) {
657- rc_path .count += append_path_string (fp , path , NULL );
658- } else {
659- const char * svcdir = rc_dirs .svcdir ? rc_dirs .svcdir : RC_SVCDIR ;
660673
661- /* first check config paths, then data paths.
662- * and within those, check dynamic paths first, then hardcoded ones */
663- rc_path .count += append_path_xdg (fp , rc_dirs .confdir , "XDG_CONFIG_DIRS" , "/etc/xdg" , user );
664- rc_path .count += append_path_array (fp , ARRAY_SIZE (config_path ), config_path , user );
665- rc_path .count += append_path (fp , strlen (svcdir ), svcdir , NULL );
674+ while ((entry = strnsep (& path , & size , ':' ))) {
675+ if (size )
676+ append_path (fp , "%.*s" , (int )size , entry );
677+ else if (user && !has_user )
678+ append_user_path (fp ), has_user = true;
679+ else if (!user ) while (* rc_path .entries )
680+ append_path (fp , "%s" , * rc_path .entries ++ );
666681 }
667- xclose_memstream (fp );
668-
669- rc_path .entries = calloc (rc_path .count + 1 , sizeof (* rc_path .entries ));
682+ }
670683
671- for (size_t count = 0 , i = 0 ; i < size && count < rc_path .count ; i += strlen (& rc_path .buffer [i ]) + 1 )
672- rc_path .entries [count ++ ] = & rc_path .buffer [i ];
673- rc_path .entries [rc_path .count ] = NULL ;
684+ static void
685+ load_dynamic_path (bool user )
686+ {
687+ const char * path , * entry ;
688+ size_t size , count = 0 ;
689+ FILE * fp ;
674690
675691 if (!rc_dirs .set ) {
676692 atexit (free_rc_dirs );
677693 rc_dirs .set = true;
678694 }
695+
696+ rc_path .entries = config_path ;
697+ rc_path .count = ARRAY_SIZE (config_path ) - 1 ;
698+
699+ if (!(path = getenv ("RC_PATH" )) && !user )
700+ return ;
701+
702+ rc_path .count = 0 ;
703+ fp = xopen_memstream (& rc_path .buffer , & size );
704+ if (path )
705+ append_rc_path (fp , path , user );
706+ else
707+ append_user_path (fp );
708+ xclose_memstream (fp );
709+
710+ rc_path .allocd = rc_path .entries = calloc (rc_path .count + 1 , sizeof (* rc_path .entries ));
711+
712+ path = rc_path .buffer ;
713+
714+ while ((entry = strnullsep (& path , & size )) && count < rc_path .count )
715+ rc_path .entries [count ++ ] = entry ;
716+ rc_path .entries [rc_path .count ] = NULL ;
679717}
680718
681719static bool is_user = false;
0 commit comments