summaryrefslogtreecommitdiff
path: root/src/logic/slbt_exec_stoolie.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/logic/slbt_exec_stoolie.c')
-rw-r--r--src/logic/slbt_exec_stoolie.c371
1 files changed, 371 insertions, 0 deletions
diff --git a/src/logic/slbt_exec_stoolie.c b/src/logic/slbt_exec_stoolie.c
new file mode 100644
index 0000000..698faaa
--- /dev/null
+++ b/src/logic/slbt_exec_stoolie.c
@@ -0,0 +1,371 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <sys/stat.h>
+#include <slibtool/slibtool.h>
+#include <slibtool/slibtool_output.h>
+#include "slibtool_driver_impl.h"
+#include "slibtool_stoolie_impl.h"
+#include "slibtool_errinfo_impl.h"
+#include "slibtool_realpath_impl.h"
+#include "slibtool_snprintf_impl.h"
+#include "slibtool_symlink_impl.h"
+#include "argv/argv.h"
+
+static const char slbt_this_dir[2] = {'.',0};
+
+static int slbt_stoolie_usage(
+ int fdout,
+ const char * program,
+ const char * arg,
+ const struct argv_option ** optv,
+ struct argv_meta * meta,
+ struct slbt_exec_ctx * ectx,
+ int noclr)
+{
+ char header[512];
+ bool stooliemode;
+
+ stooliemode = !strcmp(program,"slibtoolize");
+
+ snprintf(header,sizeof(header),
+ "Usage: %s%s [options] ...\n"
+ "Options:\n",
+ program,
+ stooliemode ? "" : " --mode=slibtoolize");
+
+ switch (noclr) {
+ case 0:
+ slbt_argv_usage(fdout,header,optv,arg);
+ break;
+
+ default:
+ slbt_argv_usage_plain(fdout,header,optv,arg);
+ break;
+ }
+
+ if (ectx)
+ slbt_ectx_free_exec_ctx(ectx);
+
+ slbt_argv_free(meta);
+
+ return SLBT_USAGE;
+}
+
+static int slbt_exec_stoolie_fail(
+ struct slbt_exec_ctx * ectx,
+ struct argv_meta * meta,
+ int ret)
+{
+ slbt_argv_free(meta);
+ slbt_ectx_free_exec_ctx(ectx);
+ return ret;
+}
+
+static int slbt_exec_stoolie_remove_file(
+ const struct slbt_driver_ctx * dctx,
+ int fddst,
+ const char * target)
+{
+ /* remove target (if any) */
+ if (!unlinkat(fddst,target,0) || (errno == ENOENT))
+ return 0;
+
+ return SLBT_SYSTEM_ERROR(dctx,0);
+}
+
+static int slbt_exec_stoolie_perform_actions(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ struct slbt_stoolie_ctx * stctx)
+{
+ struct slbt_stoolie_ctx_impl * ictx;
+ struct stat st;
+ char m4dir [PATH_MAX];
+ char auxdir[PATH_MAX];
+ char slibm4[PATH_MAX];
+ char ltmain[PATH_MAX];
+ bool fslibm4;
+ bool fltmain;
+
+ ictx = slbt_get_stoolie_ictx(stctx);
+
+ /* source files */
+ if (slbt_snprintf(
+ slibm4,sizeof(slibm4),"%s/%s",
+ SLBT_PACKAGE_DATADIR,
+ "slibtool.m4") < 0)
+ return SLBT_BUFFER_ERROR(dctx);
+
+ if (slbt_snprintf(
+ ltmain,sizeof(slibm4),"%s/%s",
+ SLBT_PACKAGE_DATADIR,
+ "ltmain.sh") < 0)
+ return SLBT_BUFFER_ERROR(dctx);
+
+ /* --force? */
+ if (dctx->cctx->drvflags & SLBT_DRIVER_STOOLIE_FORCE) {
+ if (ictx->fdm4 >= 0)
+ if (slbt_exec_stoolie_remove_file(dctx,ictx->fdm4,"slibtool.m4") < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (slbt_exec_stoolie_remove_file(dctx,ictx->fdaux,"ltmain.sh") < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ fslibm4 = (ictx->fdm4 >= 0);
+ fltmain = true;
+ } else {
+ if (ictx->fdm4 < 0) {
+ fslibm4 = false;
+
+ } else if (fstatat(ictx->fdm4,"slibtool.m4",&st,AT_SYMLINK_NOFOLLOW) == 0) {
+ fslibm4 = false;
+
+ } else if (errno == ENOENT) {
+ fslibm4 = true;
+
+ } else {
+ return SLBT_SYSTEM_ERROR(dctx,"slibtool.m4");
+ }
+
+ if (fstatat(ictx->fdaux,"ltmain.sh",&st,AT_SYMLINK_NOFOLLOW) == 0) {
+ fltmain = false;
+
+ } else if (errno == ENOENT) {
+ fltmain = true;
+
+ } else {
+ return SLBT_SYSTEM_ERROR(dctx,"ltmain.sh");
+ }
+ }
+
+ /* --copy? */
+ if (dctx->cctx->drvflags & SLBT_DRIVER_STOOLIE_COPY) {
+ if (fslibm4) {
+ if (slbt_realpath(ictx->fdm4,".",0,m4dir,sizeof(m4dir)) < 0)
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ if (slbt_util_copy_file(ectx,slibm4,m4dir) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+ }
+
+ if (fltmain) {
+ if (slbt_realpath(ictx->fdaux,".",0,auxdir,sizeof(auxdir)) < 0)
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ if (slbt_util_copy_file(ectx,ltmain,auxdir) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+ }
+ } else {
+ /* default to symlinks */
+ if (fslibm4)
+ if (slbt_create_symlink_ex(
+ dctx,ectx,
+ ictx->fdm4,
+ slibm4,
+ "slibtool.m4",
+ SLBT_SYMLINK_LITERAL) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (fltmain)
+ if (slbt_create_symlink_ex(
+ dctx,ectx,
+ ictx->fdaux,
+ ltmain,
+ "ltmain.sh",
+ SLBT_SYMLINK_LITERAL) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+ }
+
+ return 0;
+}
+
+int slbt_exec_stoolie(const struct slbt_driver_ctx * dctx)
+{
+ int ret;
+ int fdout;
+ int fderr;
+ char ** argv;
+ char ** iargv;
+ struct slbt_exec_ctx * ectx;
+ struct slbt_driver_ctx_impl * ictx;
+ const struct slbt_common_ctx * cctx;
+ struct argv_meta * meta;
+ struct argv_entry * entry;
+ size_t nunits;
+ size_t cunits;
+ const char ** unitv;
+ const char ** unitp;
+ struct slbt_stoolie_ctx ** stctxv;
+ struct slbt_stoolie_ctx ** stctxp;
+ const struct argv_option * optv[SLBT_OPTV_ELEMENTS];
+
+ /* context */
+ if (slbt_ectx_get_exec_ctx(dctx,&ectx) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ /* initial state, slibtoolize (stoolie) mode skin */
+ slbt_ectx_reset_arguments(ectx);
+ slbt_disable_placeholders(ectx);
+
+ ictx = slbt_get_driver_ictx(dctx);
+ cctx = dctx->cctx;
+ iargv = ectx->cargv;
+
+ fdout = slbt_driver_fdout(dctx);
+ fderr = slbt_driver_fderr(dctx);
+
+ (void)fderr;
+
+ /* <stoolie> argv meta */
+ slbt_optv_init(slbt_stoolie_options,optv);
+
+ if (!(meta = slbt_argv_get(
+ iargv,optv,
+ dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS
+ ? ARGV_VERBOSITY_ERRORS
+ : ARGV_VERBOSITY_NONE,
+ fdout)))
+ return slbt_exec_stoolie_fail(
+ ectx,meta,
+ SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_AR_FAIL));
+
+ /* dest, alternate argument vector options */
+ argv = ectx->altv;
+ *argv++ = iargv[0];
+ nunits = 0;
+
+ for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
+ if (entry->fopt) {
+ switch (entry->tag) {
+ case TAG_STLE_HELP:
+ slbt_stoolie_usage(
+ fdout,
+ dctx->program,
+ 0,optv,0,ectx,
+ dctx->cctx->drvflags
+ & SLBT_DRIVER_ANNOTATE_NEVER);
+
+ ictx->cctx.drvflags |= SLBT_DRIVER_VERSION;
+ ictx->cctx.drvflags ^= SLBT_DRIVER_VERSION;
+
+ slbt_argv_free(meta);
+
+ return SLBT_OK;
+
+ case TAG_STLE_VERSION:
+ ictx->cctx.drvflags |= SLBT_DRIVER_VERSION;
+ break;
+
+ case TAG_STLE_COPY:
+ ictx->cctx.drvflags |= SLBT_DRIVER_STOOLIE_COPY;
+ break;
+
+ case TAG_STLE_FORCE:
+ ictx->cctx.drvflags |= SLBT_DRIVER_STOOLIE_FORCE;
+ break;
+
+ case TAG_STLE_INSTALL:
+ ictx->cctx.drvflags |= SLBT_DRIVER_STOOLIE_INSTALL;
+ break;
+
+ case TAG_STLE_DEBUG:
+ ictx->cctx.drvflags |= SLBT_DRIVER_DEBUG;
+ break;
+
+ case TAG_STLE_DRY_RUN:
+ ictx->cctx.drvflags |= SLBT_DRIVER_DRY_RUN;
+ break;
+
+ case TAG_STLE_SILENT:
+ ictx->cctx.drvflags &= ~(uint64_t)SLBT_DRIVER_VERBOSE;
+ ictx->cctx.drvflags |= SLBT_DRIVER_SILENT;
+ break;
+
+ case TAG_STLE_VERBOSE:
+ ictx->cctx.drvflags &= ~(uint64_t)SLBT_DRIVER_SILENT;
+ ictx->cctx.drvflags |= SLBT_DRIVER_VERBOSE;
+ break;
+ }
+
+ if (entry->fval) {
+ *argv++ = (char *)entry->arg;
+ }
+ } else {
+ nunits++;
+ };
+ }
+
+ /* defer --version printing to slbt_main() as needed */
+ if (cctx->drvflags & SLBT_DRIVER_VERSION) {
+ slbt_argv_free(meta);
+ slbt_ectx_free_exec_ctx(ectx);
+ return SLBT_OK;
+ }
+
+ /* default to this-dir as needed */
+ if (!(cunits = nunits))
+ nunits++;
+
+ /* slibtoolize target directory vector allocation */
+ if (!(stctxv = calloc(nunits+1,sizeof(struct slbt_stoolie_ctx *))))
+ return slbt_exec_stoolie_fail(
+ ectx,meta,
+ SLBT_SYSTEM_ERROR(dctx,0));
+
+ /* unit vector allocation */
+ if (!(unitv = calloc(nunits+1,sizeof(const char *)))) {
+ free (stctxv);
+
+ return slbt_exec_stoolie_fail(
+ ectx,meta,
+ SLBT_SYSTEM_ERROR(dctx,0));
+ }
+
+ /* unit vector initialization */
+ for (entry=meta->entries,unitp=unitv; entry->fopt || entry->arg; entry++)
+ if (!entry->fopt)
+ *unitp++ = entry->arg;
+
+ if (!cunits)
+ unitp[0] = slbt_this_dir;
+
+ /* slibtoolize target directory vector initialization */
+ for (unitp=unitv,stctxp=stctxv; *unitp; unitp++,stctxp++) {
+ if (slbt_st_get_stoolie_ctx(dctx,*unitp,stctxp) < 0) {
+ for (stctxp=stctxv; *stctxp; stctxp++)
+ slbt_st_free_stoolie_ctx(*stctxp);
+
+ free(unitv);
+ free(stctxv);
+
+ return slbt_exec_stoolie_fail(
+ ectx,meta,
+ SLBT_NESTED_ERROR(dctx));
+ }
+ }
+
+ /* slibtoolize operations */
+ for (ret=0,stctxp=stctxv; !ret && *stctxp; stctxp++)
+ ret = slbt_exec_stoolie_perform_actions(dctx,ectx,*stctxp);
+
+ /* all done */
+ for (stctxp=stctxv; *stctxp; stctxp++)
+ slbt_st_free_stoolie_ctx(*stctxp);
+
+ free(unitv);
+ free(stctxv);
+
+ slbt_argv_free(meta);
+ slbt_ectx_free_exec_ctx(ectx);
+
+ return ret;
+}
+
+int slbt_exec_slibtoolize(const struct slbt_driver_ctx * dctx)
+{
+ return slbt_exec_stoolie(dctx);
+}