code:
Search for xfce4 panel plugins in the directories specified
in XDG_DATA_DIRS and X_XFCE4_LIB_DIRS.  For discussion of the
relevant issues, see:

  https://bugzilla.xfce.org/show_bug.cgi?id=5455

Patch by Mark H Weaver <mhw@netris.org>

--- xfce4-panel-4.10.0/panel/panel-module.c.orig	2012-04-28 16:31:35.000000000 -0400
+++ xfce4-panel-4.10.0/panel/panel-module.c	2014-12-14 01:31:55.728107386 -0500
@@ -35,8 +35,14 @@
 #include <panel/panel-plugin-external-wrapper.h>
 #include <panel/panel-plugin-external-46.h>

-#define PANEL_PLUGINS_LIB_DIR (LIBDIR G_DIR_SEPARATOR_S "panel" G_DIR_SEPARATOR_S "plugins")
-#define PANEL_PLUGINS_LIB_DIR_OLD (LIBDIR G_DIR_SEPARATOR_S "panel-plugins")
+#define PANEL_PLUGINS_LIB_DIR_TAIL (G_DIR_SEPARATOR_S "panel" G_DIR_SEPARATOR_S "plugins")
+#define PANEL_PLUGINS_LIB_DIR_TAIL_OLD (G_DIR_SEPARATOR_S "panel-plugins")
+
+static const gchar *plugins_lib_dir_tails[] =
+{
+  PANEL_PLUGINS_LIB_DIR_TAIL,
+  PANEL_PLUGINS_LIB_DIR_TAIL_OLD
+};

 typedef enum _PanelModuleRunMode PanelModuleRunMode;
@@ -335,21 +341,39 @@
           /* show a messsage if the old module path key still exists */
           g_message ("Plugin %s: The \"X-XFCE-Module-Path\" key is "
                      "ignored in \"%s\", the panel will look for the "
-                     "module in %s. See bug #5455 why this decision was made",
-                     name, filename, PANEL_PLUGINS_LIB_DIR);
+                     "module in DIR%s for each DIR in $X_XFCE4_LIB_DIRS "
+                     "(%s by default).  See bug #5455 for discussion.",
+                     name, filename, PANEL_PLUGINS_LIB_DIR_TAIL, LIBDIR);
         }
 #endif

-      path = g_module_build_path (PANEL_PLUGINS_LIB_DIR, module_name);
-      found = g_file_test (path, G_FILE_TEST_EXISTS);
+      /* search for module */
+      {
+        gchar   *dirs_string;
+        gchar  **dirs;
+        int      i, j;
+
+        dirs_string = (gchar *) g_getenv ("X_XFCE4_LIB_DIRS");
+        if (!dirs_string)
+          dirs_string = LIBDIR;
+        dirs = g_strsplit (dirs_string, G_SEARCHPATH_SEPARATOR_S, 0);
+
+        found = FALSE;
+        path = NULL;
+
+        for (i = 0; !found && dirs[i] != NULL; i++)
+          for (j = 0; !found && j < G_N_ELEMENTS (plugins_lib_dir_tails); j++)
+            {
+              gchar *dir = g_strconcat (dirs[i], plugins_lib_dir_tails[j], NULL);
+
+              g_free (path);
+              path = g_module_build_path (dir, module_name);
+              found = g_file_test (path, G_FILE_TEST_EXISTS);
+              g_free (dir);
+            }

-      if (!found)
-        {
-          /* deprecated location for module plugin directories */
-          g_free (path);
-          path = g_module_build_path (PANEL_PLUGINS_LIB_DIR_OLD, module_name);
-          found = g_file_test (path, G_FILE_TEST_EXISTS);
-        }
+        g_strfreev (dirs);
+      }

       if (G_LIKELY (found))
         {
--- xfce4-panel-4.10.0/panel/panel-module-factory.c.orig	2012-04-28 16:31:35.000000000 -0400
+++ xfce4-panel-4.10.0/panel/panel-module-factory.c	2014-12-13 23:55:27.439404812 -0500
@@ -42,6 +42,11 @@
 #define PANEL_PLUGINS_DATA_DIR     (DATADIR G_DIR_SEPARATOR_S "panel" G_DIR_SEPARATOR_S "plugins")
 #define PANEL_PLUGINS_DATA_DIR_OLD (DATADIR G_DIR_SEPARATOR_S "panel-plugins")

+static const gchar *plugins_data_dir_tails[] =
+{
+  (G_DIR_SEPARATOR_S "xfce4" G_DIR_SEPARATOR_S "panel" G_DIR_SEPARATOR_S "plugins"),
+  (G_DIR_SEPARATOR_S "xfce4" G_DIR_SEPARATOR_S "panel-plugins")
+};

 static void     panel_module_factory_finalize        (GObject                  *object);
@@ -223,8 +228,22 @@
 panel_module_factory_load_modules (PanelModuleFactory *factory,
                                    gboolean            warn_if_known)
 {
+  const gchar * const * system_data_dirs;
+  int i, j;
+
   panel_return_if_fail (PANEL_IS_MODULE_FACTORY (factory));

+  system_data_dirs = g_get_system_data_dirs ();
+  for (i = 0; system_data_dirs[i] != NULL; i++)
+    for (j = 0; j < G_N_ELEMENTS (plugins_data_dir_tails); j++)
+    {
+      gchar *dir;
+
+      dir = g_strconcat (system_data_dirs[i], plugins_data_dir_tails[j], NULL);
+      panel_module_factory_load_modules_dir (factory, dir, warn_if_known);
+      g_free (dir);
+    }
+
   /* load from the new and old location */
   panel_module_factory_load_modules_dir (factory, PANEL_PLUGINS_DATA_DIR, warn_if_known);
   panel_module_factory_load_modules_dir (factory, PANEL_PLUGINS_DATA_DIR_OLD, warn_if_known);


code:
This patch make Xfce use "gnome" as the default icon theme and enable font antialias.

Taken from ArchLinux.

diff -upr xfce4-settings-4.12.0.orig/xfsettingsd/xsettings.xml xfce4-settings-4.12.0/xfsettingsd/xsettings.xml
--- xfce4-settings-4.12.0.orig/xfsettingsd/xsettings.xml	2015-02-24 03:33:11.000000000 +0200
+++ xfce4-settings-4.12.0/xfsettingsd/xsettings.xml	2015-03-01 09:52:24.376869688 +0200
@@ -6,8 +6,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <channel name="xsettings" version="1.0">
   <property name="Net" type="empty">
     <property name="ThemeName" type="empty"/>
-    <property name="IconThemeName" type="empty"/>
+    <property name="IconThemeName" type="string" value="gnome"/>
     <property name="DoubleClickTime" type="int" value="400"/>
     <property name="DoubleClickDistance" type="int" value="5"/>
     <property name="DndDragThreshold" type="int" value="8"/>
@@ -19,9 +19,9 @@
   </property>
   <property name="Xft" type="empty">
     <property name="DPI" type="empty"/>
-    <property name="Antialias" type="int" value="-1"/>
+    <property name="Antialias" type="int" value="1"/>
     <property name="Hinting" type="int" value="-1"/>
-    <property name="HintStyle" type="string" value="hintnone"/>
+    <property name="HintStyle" type="string" value="hintfull"/>
     <property name="RGBA" type="string" value="none"/>
     <!-- <property name="Lcdfilter" type="string" value="none"/> -->
   </property>

repo_name: maximed/guix

license: mit


code:
This patch is required for xmonad to make use of shared libraries.
Without it, xmonad will not work since we do not (by default) use
statically linked Haskell libraries.

diff -ruN xmonad-0.15-a/src/XMonad/Core.hs xmonad-0.15-b/src/XMonad/Core.hs
--- xmonad-0.15-a/src/XMonad/Core.hs	1969-12-31 19:00:00.000000000 -0500
+++ xmonad-0.15-b/src/XMonad/Core.hs	1969-12-31 19:00:00.000000000 -0500
@@ -681,6 +681,8 @@
        compileGHC bin dir errHandle =
          runProcess "ghc" ["--make"
                           , "xmonad.hs"
+                          , "-dynamic"
+                          , "-fPIC"
                           , "-i"
                           , "-ilib"
                           , "-fforce-recomp"


code:
Author: Eric Bavier Date: 2020-01-13
Url: https://notabug.org/bavier/guix-bavier/raw/master/bavier/patches/
+xplanet-cxx11-eof.patch

diff --git a/src/libannotate/addArcs.cpp b/src/libannotate/addArcs.cpp
index 2ee06c0..4fdb343 100644
--- a/src/libannotate/addArcs.cpp
+++ b/src/libannotate/addArcs.cpp
@@ -258,7 +258,7 @@ addArcs(PlanetProperties *planetProperties, Planet *planet,
         {
             ifstream inFile(arcFile.c_str());
             char *line = new char[MAX_LINE_LENGTH];
-            while (inFile.getline (line, MAX_LINE_LENGTH, '\n') != NULL)
+            while (!inFile.getline (line, MAX_LINE_LENGTH, '\n').eof())
                 readArcFile(line, planet, view, projection,
                             planetProperties, annotationMap);

@@ -292,7 +292,7 @@ addArcs(View *view, multimap<double, Annotation *> &annotationMap)
         {
             ifstream inFile(arcFile.c_str());
             char *line = new char[256];
-            while (inFile.getline (line, 256, '\n') != NULL)
+            while (!inFile.getline (line, 256, '\n').eof())
                 readArcFile(line, NULL, view, NULL, NULL, annotationMap);

             inFile.close();
diff --git a/src/libannotate/addMarkers.cpp b/src/libannotate/addMarkers.cpp
index dde51c1..b641e6a 100644
--- a/src/libannotate/addMarkers.cpp
+++ b/src/libannotate/addMarkers.cpp
@@ -429,7 +429,7 @@ addMarkers(PlanetProperties *planetProperties, Planet *planet,
         {
             ifstream inFile(markerFile.c_str());
             char *line = new char[MAX_LINE_LENGTH];
-            while (inFile.getline (line, MAX_LINE_LENGTH, '\n') != NULL)
+            while (!inFile.getline (line, MAX_LINE_LENGTH, '\n').eof())
             {
                 unsigned char color[3];
                 memcpy(color, planetProperties->MarkerColor(), 3);
@@ -475,7 +475,7 @@ addMarkers(View *view, const int width, const int height,
         {
             ifstream inFile(markerFile.c_str());
             char *line = new char[MAX_LINE_LENGTH];
-            while (inFile.getline (line, MAX_LINE_LENGTH, '\n') != NULL)
+            while (!inFile.getline (line, MAX_LINE_LENGTH, '\n').eof())
             {
                 unsigned char color[3];
                 memcpy(color, options->Color(), 3);
diff --git a/src/libannotate/addSatellites.cpp b/src/libannotate/addSatellites.cpp
index 2634339..6d9d378 100644
--- a/src/libannotate/addSatellites.cpp
+++ b/src/libannotate/addSatellites.cpp
@@ -488,10 +488,10 @@ loadSatelliteVector(PlanetProperties *planetProperties)
         {
             ifstream inFile(tleFile.c_str());
             char lines[3][80];
-            while (inFile.getline(lines[0], 80) != NULL)
+            while (!inFile.getline(lines[0], 80).eof())
             {
-                if ((inFile.getline(lines[1], 80) == NULL)
-                    || (inFile.getline(lines[2], 80) == NULL))
+	        if ((inFile.getline(lines[1], 80).eof())
+                    || (inFile.getline(lines[2], 80).eof()))
                 {
                     ostringstream errStr;
                     errStr << "Malformed TLE file (" << tleFile << ")?\n";
@@ -542,7 +542,7 @@ addSatellites(PlanetProperties *planetProperties, Planet *planet,
         {
             ifstream inFile(satFile.c_str());
             char *line = new char[MAX_LINE_LENGTH];
-            while (inFile.getline (line, MAX_LINE_LENGTH, '\n') != NULL)
+            while (!inFile.getline (line, MAX_LINE_LENGTH, '\n').eof())
                 readSatelliteFile(line, planet, view, projection,
                                   planetProperties, annotationMap);

diff --git a/src/libannotate/addSpiceObjects.cpp b/src/libannotate/addSpiceObjects.cpp
index 67b752c..eeadf6e 100644
--- a/src/libannotate/addSpiceObjects.cpp
+++ b/src/libannotate/addSpiceObjects.cpp
@@ -524,7 +524,7 @@ processSpiceKernels(const bool load)
         {
             ifstream inFile(kernelFile.c_str());
             char *line = new char[MAX_LINE_LENGTH];
-            while (inFile.getline(line, MAX_LINE_LENGTH, '\n') != NULL)
+            while (!inFile.getline(line, MAX_LINE_LENGTH, '\n').eof())
             {
                 int ii = 0;
                 while (isDelimiter(line[ii]))
@@ -576,7 +576,7 @@ addSpiceObjects(map<double, Planet *> &planetsFromSunMap,
         {
             ifstream inFile(spiceFile.c_str());
             char *line = new char[MAX_LINE_LENGTH];
-            while (inFile.getline(line, MAX_LINE_LENGTH, '\n') != NULL)
+            while (!inFile.getline(line, MAX_LINE_LENGTH, '\n').eof())
                 readSpiceFile(line, planetsFromSunMap, view, projection,
                               annotationMap);
             inFile.close();
diff --git a/src/libmultiple/RayleighScattering.cpp b/src/libmultiple/RayleighScattering.cpp
index d885173..1be8ece 100644
--- a/src/libmultiple/RayleighScattering.cpp
+++ b/src/libmultiple/RayleighScattering.cpp
@@ -369,7 +369,7 @@ RayleighScattering::readConfigFile(string configFile)

     diskTemplate_.clear();
     limbTemplate_.clear();
-    while (inFile.getline(line, MAX_LINE_LENGTH, '\n') != NULL)
+    while (!inFile.getline(line, MAX_LINE_LENGTH, '\n').eof())
     {
         int i = 0;
         while (isDelimiter(line[i]))
@@ -439,7 +439,7 @@ RayleighScattering::readBlock(ifstream &inFile,
     values.clear();

     char line[MAX_LINE_LENGTH];
-    while (inFile.getline(line, MAX_LINE_LENGTH, '\n') != NULL)
+    while (!inFile.getline(line, MAX_LINE_LENGTH, '\n').eof())
     {
         int i = 0;
         while (isDelimiter(line[i]))
@@ -470,7 +470,7 @@ RayleighScattering::readValue(ifstream &inFile,
                               double &value)
 {
     char line[MAX_LINE_LENGTH];
-    while (inFile.getline(line, MAX_LINE_LENGTH, '\n') != NULL)
+    while (!inFile.getline(line, MAX_LINE_LENGTH, '\n').eof())
     {
         int i = 0;
         while (isDelimiter(line[i]))
diff --git a/src/libmultiple/drawStars.cpp b/src/libmultiple/drawStars.cpp
index ff07c49..aabdfed 100644
--- a/src/libmultiple/drawStars.cpp
+++ b/src/libmultiple/drawStars.cpp
@@ -41,7 +41,7 @@ drawStars(DisplayBase *display, View *view)
     ifstream inFile(starMap.c_str());

     char line[MAX_LINE_LENGTH];
-    while (inFile.getline(line, MAX_LINE_LENGTH, '\n') != NULL)
+    while (!inFile.getline(line, MAX_LINE_LENGTH, '\n').eof())
     {
         if (line[0] == '#') continue;

diff --git a/src/readConfig.cpp b/src/readConfig.cpp
index cc1964f..4650527 100644
--- a/src/readConfig.cpp
+++ b/src/readConfig.cpp
@@ -550,7 +550,7 @@ readConfigFile(string configFile, PlanetProperties *planetProperties[])

         ifstream inFile(configFile.c_str());
         char *line = new char[256];
-        while (inFile.getline(line, 256, '\n') != NULL)
+        while (!inFile.getline(line, 256, '\n').eof())
             readConfig(line, planetProperties);

         // This condition will only be true if [default] is the only


code:
Origin: $NetBSD: patch-src_libdisplay_DisplayOutput.cpp,v 1.1 2019/11/16 17:36:28 ng0 Exp $

Modified by: R Veera Kumar <vkor@vkten.in> 2020-03-28; change to patch -p1

diff -uNr xplanet-1.3.1/src/libdisplay/DisplayOutput.cpp xplanet-1.3.1.new/src/libdisplay/DisplayOutput.cpp
--- xplanet-1.3.1/src/libdisplay/DisplayOutput.cpp	2013-02-17 01:07:47.000000000 +0530
+++ xplanet-1.3.1.new/src/libdisplay/DisplayOutput.cpp	2020-03-28 22:08:44.432499170 +0530
@@ -51,7 +51,7 @@
     string outputFilename = options->OutputBase();
     int startIndex = options->OutputStartIndex();
     int stopIndex = options->NumTimes() + startIndex - 1;
-    if (stopIndex > 1)
+    if (stopIndex > 0)
     {
         const int digits = (int) (log10((double) stopIndex) + 1);
         char buffer[64];


code:
Origin: $NetBSD: patch-src_libimage_gif.c,v 1.4 2019/11/16 17:36:28 ng0 Exp $

Modified by: R Veera Kumar <vkor@vkten.in> 2020-03-28; change to patch -p1

diff -uNr xplanet-1.3.1/src/libimage/gif.c xplanet-1.3.1.new/src/libimage/gif.c
--- xplanet-1.3.1/src/libimage/gif.c	2013-02-17 01:07:47.000000000 +0530
+++ xplanet-1.3.1.new/src/libimage/gif.c	2020-03-28 22:15:24.444309199 +0530
@@ -21,7 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-
+#include <stdbool.h>
 #include <gif_lib.h>

 /*
@@ -178,8 +178,12 @@
 	    *BufferP++ = ColorMapEntry->Blue;
 	}
     }
-
+
+#if GIFLIB_MAJOR >= 5
+    if (DGifCloseFile(GifFile, NULL) == GIF_ERROR) {
+#else
     if (DGifCloseFile(GifFile) == GIF_ERROR) {
+#endif
 	return(0);
     }

@@ -493,7 +497,11 @@
 static void QuitGifError(GifFileType *GifFile)
 {
     fprintf(stderr, "Error writing GIF file\n");
+#if GIFLIB_MAJOR >= 5
+    if (GifFile != NULL) EGifCloseFile(GifFile, NULL);
+#else
     if (GifFile != NULL) EGifCloseFile(GifFile);
+#endif
 }

 int
@@ -589,7 +597,11 @@
 	Ptr += width;
     }

+#if GIFLIB_MAJOR >= 5
+    if (EGifCloseFile(GifFile, NULL) == GIF_ERROR)
+#else
     if (EGifCloseFile(GifFile) == GIF_ERROR)
+#endif

     {
 	QuitGifError(GifFile);


code:
Disable systemd-run if the command is not found.

diff -ru xpra-4.2~/xpra/scripts/main.py xpra-4.2/xpra/scripts/main.py
--- xpra-4.2~/xpra/scripts/main.py	2021-06-06 08:51:13.756815842 -0700
+++ xpra-4.2/xpra/scripts/main.py	2021-06-06 16:07:13.371024486 -0700
@@ -331,23 +331,26 @@
     if not is_systemd_pid1():
         return False    # pragma: no cover
     #test it:
-    cmd = ["systemd-run", "--quiet", "--user", "--scope", "--", "true"]
-    proc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=False)
     try:
-        proc.communicate(timeout=2)
-        r = proc.returncode
-    except TimeoutExpired:  # pragma: no cover
-        r = None
-    if r is None:
+        cmd = ["systemd-run", "--quiet", "--user", "--scope", "--", "true"]
+        proc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=False)
         try:
-            proc.terminate()
-        except Exception:
-            pass
-        try:
-            proc.communicate(timeout=1)
+            proc.communicate(timeout=2)
+            r = proc.returncode
         except TimeoutExpired:  # pragma: no cover
             r = None
-    return r==0
+        if r is None:
+            try:
+                proc.terminate()
+            except Exception:
+                pass
+            try:
+                proc.communicate(timeout=1)
+            except TimeoutExpired:  # pragma: no cover
+                r = None
+        return r==0
+    except FileNotFoundError:
+        return False

 def run_mode(script_file, error_cb, options, args, mode, defaults):


code:
From bbd54510f0297afa2d1a81927db060cb0b791f14 Mon Sep 17 00:00:00 2001
From: Ralph Little <littlesincanada@yahoo.co.uk>
Date: Sun, 1 Sep 2019 17:34:19 -0700
Subject: [PATCH] Apply opensuse upstream patch xsane_memory_leak

Removes completely redundant memory allocation.
---
 src/xsane-batch-scan.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/xsane-batch-scan.c b/src/xsane-batch-scan.c
index 90cc0e0..e77caca 100644
--- a/src/xsane-batch-scan.c
+++ b/src/xsane-batch-scan.c
@@ -680,7 +680,6 @@ static GtkWidget *xsane_batch_scan_create_list_entry(Batch_Scan_Parameters *para
  GtkWidget *list_item;
  GtkWidget *hbox;
  int size = 120;
- char *data;

   list_item = gtk_list_item_new();

@@ -688,8 +687,6 @@ static GtkWidget *xsane_batch_scan_create_list_entry(Batch_Scan_Parameters *para
   gtk_container_add(GTK_CONTAINER(list_item), hbox);
   gtk_widget_show(hbox);

-  data = calloc(size, size);
-
   parameters->gtk_preview = gtk_preview_new(GTK_PREVIEW_COLOR);
   gtk_preview_size(GTK_PREVIEW(parameters->gtk_preview), size, size);
   gtk_box_pack_start(GTK_BOX(hbox), parameters->gtk_preview, FALSE, FALSE, 0);
--
2.22.0


code:
From c126eea11c4ee39cbe9c0c76f920626b618b6ee9 Mon Sep 17 00:00:00 2001
From: Ralph Little <littlesincanada@yahoo.co.uk>
Date: Sun, 1 Sep 2019 17:03:44 -0700
Subject: [PATCH] Apply debian upstream patch 0135-fix_pdf_floats

Original patch commentary:

Description: Fix floats in PDF and PostScript
 Set LC_NUMERIC to POSIX before printing floats when building
 PostScript or PDF output.
Author: Julien BLACHE <jblache@debian.org>
Forwarded: yes

------------
Looks like float printing format is affected by the current locale.
Ensures that we always get POSIX formatting of floats.
---
 src/xsane-save.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/xsane-save.c b/src/xsane-save.c
index f14df05..63550cc 100644
--- a/src/xsane-save.c
+++ b/src/xsane-save.c
@@ -26,6 +26,8 @@
 #include "xsane-back-gtk.h"
 #include "xsane-front-gtk.h"
 #include "xsane-save.h"
+#include <locale.h>
+#include <string.h>
 #include <time.h>
 #include <sys/wait.h>

@@ -2425,6 +2427,7 @@ static void xsane_save_ps_create_image_header(FILE *outfile,
                                               int flatedecode)
 {
  int depth;
+ char *save_locale;

   depth = image_info->depth;

@@ -2442,8 +2445,15 @@ static void xsane_save_ps_create_image_header(FILE *outfile,

   fprintf(outfile, "%d rotate\n", degree);
   fprintf(outfile, "%d %d translate\n", position_left, position_bottom);
+
+  save_locale = strdup(setlocale(LC_NUMERIC, NULL));
+  setlocale(LC_NUMERIC, "POSIX");
+
   fprintf(outfile, "%f %f scale\n", width, height);

+  setlocale(LC_NUMERIC, save_locale);
+  free(save_locale);
+
   fprintf(outfile, "<<\n");
   fprintf(outfile, " /ImageType 1\n");
   fprintf(outfile, " /Width %d\n", image_info->image_width);
@@ -3921,6 +3931,7 @@ static void xsane_save_pdf_create_page_header(FILE *outfile, struct pdf_xref *xr
  int position_left, position_bottom, box_left, box_bottom, box_right, box_top, depth;
  int left, bottom;
  float rad;
+ char *save_locale;

   DBG(DBG_proc, "xsane_save_pdf_create_page_header\n");

@@ -4035,8 +4046,16 @@ static void xsane_save_pdf_create_page_header(FILE *outfile, struct pdf_xref *xr

   fprintf(outfile, "q\n");
   fprintf(outfile, "1 0 0 1 %d %d cm\n", position_left, position_bottom); /* translate */
+
+  save_locale = strdup(setlocale(LC_NUMERIC, NULL));
+  setlocale(LC_NUMERIC, "POSIX");
+
   fprintf(outfile, "%f %f -%f %f 0 0 cm\n", cos(rad), sin(rad), sin(rad), cos(rad)); /* rotate */
   fprintf(outfile, "%f 0 0 %f 0 0 cm\n", width, height); /* scale */
+
+  setlocale(LC_NUMERIC, save_locale);
+  free(save_locale);
+
   fprintf(outfile, "BI\n");
   fprintf(outfile, "  /W %d\n", image_info->image_width);
   fprintf(outfile, "  /H %d\n", image_info->image_height);
--
2.22.0


code:
From 893a5ce1f75e5eea7c8d383038ff92a150819c9c Mon Sep 17 00:00:00 2001
From: Ralph Little <littlesincanada@yahoo.co.uk>
Date: Thu, 19 Sep 2019 22:02:33 -0700
Subject: [PATCH] xsane-*-project.c - reduced snprintf format pad to silence
 warning about too long constrant string for buffer.

---
 src/xsane-email-project.c     | 4 ++--
 src/xsane-fax-project.c       | 4 ++--
 src/xsane-multipage-project.c | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/xsane-email-project.c b/src/xsane-email-project.c
index f20cb12..ac93fc2 100644
--- a/src/xsane-email-project.c
+++ b/src/xsane-email-project.c
@@ -896,7 +896,7 @@ static void xsane_email_project_update_project_status()
   snprintf(filename, sizeof(filename), "%s/xsane-mail-list", preferences.email_project);
   projectfile = fopen(filename, "r+b"); /* r+ = read and write, position = start of file */

-  snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.email_status); /* fill 32 characters status line */
+  snprintf(buf, 33, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.email_status); /* fill 32 characters status line */
   fprintf(projectfile, "%s\n", buf); /* first line is status of email */

   fclose(projectfile);
@@ -936,7 +936,7 @@ void xsane_email_project_save()
   {
    char buf[TEXTBUFSIZE];

-    snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.email_status); /* fill 32 characters status line */
+    snprintf(buf, 33, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.email_status); /* fill 32 characters status line */
     fprintf(projectfile, "%s\n", buf); /* first line is status of email */
     gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.email_status));
     xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0);
diff --git a/src/xsane-fax-project.c b/src/xsane-fax-project.c
index f263313..0c60a97 100644
--- a/src/xsane-fax-project.c
+++ b/src/xsane-fax-project.c
@@ -452,7 +452,7 @@ static void xsane_fax_project_update_project_status()
   snprintf(filename, sizeof(filename), "%s/xsane-fax-list", preferences.fax_project);
   projectfile = fopen(filename, "r+b"); /* r+ = read and write, position = start of file */

-  snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.fax_status); /* fill 32 characters status line */
+  snprintf(buf, 33, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.fax_status); /* fill 32 characters status line */
   fprintf(projectfile, "%s\n", buf); /* first line is status of mail */

   fclose(projectfile);
@@ -498,7 +498,7 @@ void xsane_fax_project_save()
   {
    char buf[TEXTBUFSIZE];

-    snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.fax_status); /* fill 32 characters status line */
+    snprintf(buf, 33, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.fax_status); /* fill 32 characters status line */
     fprintf(projectfile, "%s\n", buf); /* first line is status of mail */
     gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.fax_status));
     xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0);
diff --git a/src/xsane-multipage-project.c b/src/xsane-multipage-project.c
index f23e5f8..9392e00 100644
--- a/src/xsane-multipage-project.c
+++ b/src/xsane-multipage-project.c
@@ -522,7 +522,7 @@ void xsane_multipage_project_save()
   {
    char buf[TEXTBUFSIZE];

-    snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.multipage_status); /* fill 32 characters status line */
+    snprintf(buf, 33, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.multipage_status); /* fill 32 characters status line */
     fprintf(projectfile, "%s\n", buf); /* first line is status of multipage */
     gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status));
     xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0);
--
2.23.0


code:
From 62d9c172f258769e3a7540fe710e013bb39a704f Mon Sep 17 00:00:00 2001
From: Ralph Little <littlesincanada@yahoo.co.uk>
Date: Sat, 7 Sep 2019 12:39:45 -0700
Subject: [PATCH] Apply opensuse upstream patch 004-ipv6-support

Appears to be related to this:
https://bugzilla.redhat.com/show_bug.cgi?id=198422

-----
Changes email socket connection code to use more IP version agnostic
calls. It appears to only be used by the scan email option and
originally comes from the RedHat IPv6 awareness program mentioned
in the bug report.

In practice, I'm not sure how practical the implementation for emailing
scans in xsane is as it does not look to support encryption, pretty
much a given in today's world.
---
 src/xsane-save.c | 96 +++++++++++++++++++++++++++++++-----------------
 1 file changed, 62 insertions(+), 34 deletions(-)

diff --git a/src/xsane-save.c b/src/xsane-save.c
index 63550cc..ff3c459 100644
--- a/src/xsane-save.c
+++ b/src/xsane-save.c
@@ -31,6 +31,8 @@
 #include <time.h>
 #include <sys/wait.h>

+#include <glib.h>
+
 /* the following test is always false */
 #ifdef _native_WIN32
 # include <winsock.h>
@@ -7540,55 +7542,81 @@ void write_email_attach_file(int fd_socket, char *boundary, FILE *infile, char *
 /* returns fd_socket if sucessfull, < 0 when error occured */
 int open_socket(char *server, int port)
 {
- int fd_socket;
- struct sockaddr_in sin;
- struct hostent *he;
+ int fd_socket, e;
+
+ struct addrinfo *ai_list, *ai;
+ struct addrinfo hints;
+ gchar *port_s;
+ gint connected;
+
+  memset(&hints, '\0', sizeof(hints));
+  hints.ai_flags = AI_ADDRCONFIG;
+  hints.ai_socktype = SOCK_STREAM;
+
+  port_s = g_strdup_printf("%d", port);
+  e = getaddrinfo(server, port_s, &hints, &ai_list);
+  g_free(port_s);

-  he = gethostbyname(server);
-  if (!he)
+  if (e != 0)
   {
-    DBG(DBG_error, "open_socket: Could not get hostname of \"%s\"\n", server);
+    DBG(DBG_error, "open_socket: Could not lookup \"%s\"\n", server);
    return -1;
   }
-  else
+
+  connected = 0;
+  for (ai = ai_list; ai != NULL && !connected; ai = ai->ai_next)
   {
-    DBG(DBG_info, "open_socket: connecting to \"%s\" = %d.%d.%d.%d\n",
-        he->h_name,
-        (unsigned char) he->h_addr_list[0][0],
-        (unsigned char) he->h_addr_list[0][1],
-        (unsigned char) he->h_addr_list[0][2],
-        (unsigned char) he->h_addr_list[0][3]);
-  }
+    gchar hostname[NI_MAXHOST];
+    gchar hostaddr[NI_MAXHOST];
+
+    /* If all else fails */
+    strncpy(hostname, "(unknown name)", NI_MAXHOST-1);
+    strncpy(hostaddr, "(unknown address)", NI_MAXHOST-1);
+
+    /* Determine canonical name and IPv4/IPv6 address */
+    (void) getnameinfo(ai->ai_addr, ai->ai_addrlen, hostname, sizeof(hostname),
+                       NULL, 0, 0);
+    (void) getnameinfo(ai->ai_addr, ai->ai_addrlen, hostaddr, sizeof(hostaddr),
+                       NULL, 0, NI_NUMERICHOST);
+
+    DBG(DBG_info, "open_socket: connecting to \"%s\" (\"%s\"): %s\n",
+        server, hostname, hostaddr);

-  if (he->h_addrtype != AF_INET)
-  {
-    DBG(DBG_error, "open_socket: Unknown address family: %d\n", he->h_addrtype);
-   return -1;
-  }
+    if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6))
+    {
+      DBG(DBG_error, "open_socket: Unknown address family: %d\n", ai->ai_family);
+      continue;
+    }

-  fd_socket = socket(AF_INET, SOCK_STREAM, 0);
+    fd_socket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);

-  if (fd_socket < 0)
-  {
-    DBG(DBG_error, "open_socket: Could not create socket: %s\n", strerror(errno));
-   return -1;
-  }
+    if (fd_socket < 0)
+    {
+      DBG(DBG_error, "open_socket: Could not create socket: %s\n", strerror(errno));
+      continue;
+    }

-/*  setsockopt (dev->ctl, level, TCP_NODELAY, &on, sizeof (on)); */
+    /*  setsockopt (dev->ctl, level, TCP_NODELAY, &on, sizeof (on)); */

-  sin.sin_port = htons(port);
-  sin.sin_family = AF_INET;
-  memcpy(&sin.sin_addr, he->h_addr_list[0], he->h_length);
+    if (connect(fd_socket, ai->ai_addr, ai->ai_addrlen) != 0)
+    {
+      DBG(DBG_error, "open_socket: Could not connect with port %d of socket: %s\n", port, strerror(errno));
+      continue;
+    }
+
+    /* All went well */
+    connected = 1;
+  }

-  if (connect(fd_socket, &sin, sizeof(sin)))
+  if (!connected)
   {
-    DBG(DBG_error, "open_socket: Could not connect with port %d of socket: %s\n", ntohs(sin.sin_port), strerror(errno));
-   return -1;
+    DBG(DBG_info, "open_socket: Could not connect to any address");
+    return -1;
   }

-  DBG(DBG_info, "open_socket: Connected with port %d\n", ntohs(sin.sin_port));
+  DBG(DBG_info, "open_socket: Connected with port %d\n", port);

- return fd_socket;
+  return fd_socket;
 }

 /* ---------------------------------------------------------------------------------------------------------------------- */
--
2.22.0


code:
From 5dc1e301a165709c60c435f00ec9bb6d7d5f21f3 Mon Sep 17 00:00:00 2001
From: Ralph Little <littlesincanada@yahoo.co.uk>
Date: Tue, 27 Aug 2019 21:40:02 -0700
Subject: [PATCH] Apply debian upstream patch 0160-fix_tighten_default_umask

Original patch commentary:

Description: Change default XSane umask from 0007 to 0077
 A default umask of 0007 can be mildly insecure in a multiuser environment,
 so tighten things up a bit and go with 0077 instead.
Author: Adrien Thebo
Bug-Debian: http://bugs.debian.org/592972
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/xsane/+bug/611950

----
As above.
---
 src/xsane.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/xsane.h b/src/xsane.h
index 67f06d4..fa04418 100644
--- a/src/xsane.h
+++ b/src/xsane.h
@@ -104,7 +104,7 @@
 #define XSANE_DEBUG_ENVIRONMENT	"XSANE_DEBUG"

 #define XSANE_PROGRESS_BAR_MIN_DELTA_PERCENT 0.025
-#define XSANE_DEFAULT_UMASK		0007
+#define XSANE_DEFAULT_UMASK		0077
 #define XSANE_HOLD_TIME			200
 #define XSANE_CONTINUOUS_HOLD_TIME	10
 #define XSANE_DEFAULT_DEVICE		"SANE_DEFAULT_DEVICE"
--
2.22.0


code:
diff --git a/cmd/yggdrasil/main.go b/cmd/yggdrasil/main.go
index 813e950..08d35cc 100644
--- a/cmd/yggdrasil/main.go
+++ b/cmd/yggdrasil/main.go
@@ -40,11 +40,12 @@ type node struct {
 	admin     module.Module // admin.AdminSocket
 }

-func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config.NodeConfig {
+func readConfig(useconf *bool, useconffile *string, extraconffile *string, normaliseconf *bool) *config.NodeConfig {
 	// Use a configuration file. If -useconf, the configuration will be read
 	// from stdin. If -useconffile, the configuration will be read from the
 	// filesystem.
 	var conf []byte
+	var extraconf []byte
 	var err error
 	if *useconffile != "" {
 		// Read the file from the filesystem
@@ -56,6 +57,21 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config
 	if err != nil {
 		panic(err)
 	}
+	if *extraconffile != "" {
+		extraconf, err = ioutil.ReadFile(*extraconffile);
+	}
+	if err != nil {
+		panic(err)
+	}
+	// Generate a new configuration - this gives us a set of sane defaults -
+	// then parse the configuration we loaded above on top of it. The effect
+	// of this is that any configuration item that is missing from the provided
+	// configuration will use a sane default.
+	cfg := config.GenerateConfig()
+	var confs [2][]byte
+	confs[0]=conf
+	confs[1]=extraconf
+	for _, conf := range confs { if len(conf)>0 {
 	// If there's a byte order mark - which Windows 10 is now incredibly fond of
 	// throwing everywhere when it's converting things into UTF-16 for the hell
 	// of it - remove it and decode back down into UTF-8. This is necessary
@@ -69,11 +85,6 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config
 			panic(err)
 		}
 	}
-	// Generate a new configuration - this gives us a set of sane defaults -
-	// then parse the configuration we loaded above on top of it. The effect
-	// of this is that any configuration item that is missing from the provided
-	// configuration will use a sane default.
-	cfg := config.GenerateConfig()
 	var dat map[string]interface{}
 	if err := hjson.Unmarshal(conf, &dat); err != nil {
 		panic(err)
@@ -112,6 +123,7 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config
 	if err = mapstructure.Decode(dat, &cfg); err != nil {
 		panic(err)
 	}
+	}}
 	return cfg
 }

@@ -164,6 +176,7 @@ func main() {
 	genconf := flag.Bool("genconf", false, "print a new config to stdout")
 	useconf := flag.Bool("useconf", false, "read HJSON/JSON config from stdin")
 	useconffile := flag.String("useconffile", "", "read HJSON/JSON config from specified file path")
+	extraconffile := flag.String("extraconffile", "", "extra (usually private) HJSON/JSON config from specified file path")
 	normaliseconf := flag.Bool("normaliseconf", false, "use in combination with either -useconf or -useconffile, outputs your configuration normalised")
 	confjson := flag.Bool("json", false, "print configuration from -genconf or -normaliseconf as JSON instead of HJSON")
 	autoconf := flag.Bool("autoconf", false, "automatic mode (dynamic IP, peer with IPv6 neighbors)")
@@ -187,7 +200,7 @@ func main() {
 		cfg = config.GenerateConfig()
 	case *useconffile != "" || *useconf:
 		// Read the configuration from either stdin or from the filesystem
-		cfg = readConfig(useconf, useconffile, normaliseconf)
+		cfg = readConfig(useconf, useconffile, extraconffile, normaliseconf)
 		// If the -normaliseconf option was specified then remarshal the above
 		// configuration and print it back to stdout. This lets the user update
 		// their configuration file with newly mapped names (like above) or to
@@ -332,7 +345,7 @@ func main() {
 			goto exit
 		case _ = <-r:
 			if *useconffile != "" {
-				cfg = readConfig(useconf, useconffile, normaliseconf)
+				cfg = readConfig(useconf, useconffile, extraconffile, normaliseconf)
 				logger.Infoln("Reloading configuration from", *useconffile)
 				n.core.UpdateConfig(cfg)
 				n.tuntap.UpdateConfig(cfg)


code:
From 3f1eaf5a1645b28ca18cfa028417dc225b7a557f Mon Sep 17 00:00:00 2001
From: Raghav Gururajan <rg@raghavgururajan.name>
Date: Mon, 5 Jul 2021 06:45:49 -0400
Subject: [PATCH] Modify the strings of referenced programs.

Pattern the strings of referenced programs, so that they can be easily
substituted with absolute paths using a custom-phase.

Co-authored-by: jgart <jgart@dismail.de>
---
 ytfzf | 198 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 99 insertions(+), 99 deletions(-)

diff --git a/ytfzf b/ytfzf
index f4d2e0d..e8bb60b 100755
--- a/ytfzf
+++ b/ytfzf
@@ -49,17 +49,17 @@ cache_dir=${YTFZF_CACHE-${cache_dir-$HOME/.cache/ytfzf}}
 #video type preference (mp4/1080p, mp4/720p, etc..)
 video_pref=${YTFZF_PREF-${video_pref-}}
 #the menu to use instead of fzf when -D is specified
-external_menu=${YTFZF_EXTMENU-${external_menu-dmenu -i -l 30 -p Search:}}
+external_menu=${YTFZF_EXTMENU-${external_menu-@dmenu@ -i -l 30 -p Search:}}
 #number of columns (characters on a line) the external menu can have
 #necessary for formatting text for external menus
 external_menu_len=${YTFZF_EXTMENU_LEN-${external_menu_len-220}}
 #player settings (players need to support streaming with youtube-dl)
 #player to use for watching the video
-video_player=${YTFZF_PLAYER-${video_player-mpv}}
+video_player=${YTFZF_PLAYER-${video_player-@mpv@}}
 #if YTFZF_PREF is specified, use this player instead
-video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-mpv --ytdl-format=}}
+video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-@mpv@ --ytdl-format=}}
 #player to use for audio only
-audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-mpv --no-video}}
+audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-@mpv@ --no-video}}
 #the command to use for displaying thumbnails
 thumb_disp_method=${YTFZF_THUMB_DISP_METHOD-${thumb_disp_method-ueberzug}}
 #Storing the argument and location for autogenerated subtitles
@@ -85,8 +85,8 @@ subscriptions_file=${subscriptions_file-$config_dir/subscriptions}
 #> stores the pid of running ytfzf sessions
 pid_file="$cache_dir/.pid"
 #> make folders that don't exist
-[ -d "$cache_dir" ] || mkdir -p "$cache_dir"
-[ -d "$thumb_dir" ] || mkdir -p "$thumb_dir"
+[ -d "$cache_dir" ] || @mkdir@ -p "$cache_dir"
+[ -d "$thumb_dir" ] || @mkdir@ -p "$thumb_dir"

 #> config settings
 #list of shortcuts to use in fzf
@@ -177,12 +177,12 @@ dep_ck () {
 	done
 	unset Dep
 }
-dep_ck "jq" "youtube-dl" "curl"
+dep_ck "@jq@" "@youtube-dl@" "@curl@"

 #only check for mpv if $YTFZF_PLAYER is set to it
 #don't check $YTFZF_PLAYER as it could be multiple commands
-[ "$video_player" = "mpv" ] && dep_ck "mpv"
+[ "$video_player" = "@mpv@" ] && dep_ck "@mpv@"

 ############################
 #       Help Texts         #
@@ -326,8 +326,8 @@ print_info () {
 }

 print_error () {
-    [ $ext_menu_notifs -eq 1 ] && notify-send "error" "$*" || printf "\033[31m$*\033[0m" >&2
-    [ $ext_menu_notifs -eq 1 ] && notify-send "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
+    [ $ext_menu_notifs -eq 1 ] && @notify-send@ "error" "$*" || printf "\033[31m$*\033[0m" >&2
+    [ $ext_menu_notifs -eq 1 ] && @notify-send@ "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
 }

 ############################
@@ -398,12 +398,12 @@ format_fzf () {
 format_menu () {
 	if [ "$is_ext_menu" -eq 0 ]; then
 		#dep_ck fzf here because it is only necessary to use here
-		dep_ck "fzf"
-		menu_command='column -t -s "$tab_space" | fzf -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
+		dep_ck "@fzf@"
+		menu_command='@column@ -t -s "$tab_space" | @fzf@ -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
 		format_fzf
 	else
 		# Dmenu doesn't render tabs so removing it
-		menu_command='tr -d "$tab_space" | '"$external_menu"
+		menu_command='@tr@ -d "$tab_space" | '"$external_menu"
 		format_ext_menu
 	fi
 }
@@ -461,13 +461,13 @@ ID="ytfzf-ueberzug"
 WIDTH=$FZF_PREVIEW_COLUMNS
 HEIGHT=$FZF_PREVIEW_LINES
 start_ueberzug () {
-    [ -e $FIFO ] || { mkfifo "$FIFO" || exit 1 ; }
-    ueberzug layer --parser json --silent < "$FIFO" &
+    [ -e $FIFO ] || { @mkfifo@ "$FIFO" || exit 1 ; }
+    @ueberzug@ layer --parser json --silent < "$FIFO" &
     exec 3>"$FIFO"
 }
 stop_ueberzug () {
     exec 3>&-
-    rm "$FIFO" > /dev/null 2>&1
+    @rm@ "$FIFO" > /dev/null 2>&1
 }

 preview_img () {
@@ -476,12 +476,12 @@ preview_img () {
 	shorturl=${args##*${tab_space}|}
 	shorturl="${shorturl%% *}"

-	json_obj=$(printf "%s" "$videos_json" | jq '.[]|select( .videoID == "'"$shorturl"'")')
+	json_obj=$(printf "%s" "$videos_json" | @jq@ '.[]|select( .videoID == "'"$shorturl"'")')

 	IFS=$tab_space read -r title channel duration views date description <<-EOF
 	$(
-		printf "%s" "$json_obj" | jq -r \
+		printf "%s" "$json_obj" | @jq@ -r \
 		'
 		[.title,.channel,.duration,.views,.date,.description]|@tsv
 		'
@@ -530,31 +530,31 @@ preview_img () {
 		} > "$FIFO" ;;
 	    catimg)
 		printf "\n"
-		catimg -w "$((thumb_width * 2))" "$IMAGE" ;;
+		@catimg@ -w "$((thumb_width * 2))" "$IMAGE" ;;
 	    jp2a)
 		printf "\n"
-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
+		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
 	    jp2a-8)
 		printf "\n"
-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
+		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
 	    jp2a-4)
 		printf "\n"
-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
+		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
 	    jp2a-gray|jp2a-grey)
 		printf "\n"
-		jp2a --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
+		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
 	    chafa)
 		printf "\n"
-		chafa --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
+		@chafa@ --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
 	    chafa-gray|chafa-grey)
 		printf "\n"
-		chafa --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
+		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
 	    chafa-4)
 		printf "\n"
-		chafa --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
+		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
 	    chafa-8)
 		printf "\n"
-		chafa --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
+		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
 	    custom)
 		if ! function_exists "handle_display_img"; then
 		    printf "\033[031mERROR[#07]: \033[0m\033[1mhandle_display_img\033[0m is not defined" >&2
@@ -585,20 +585,20 @@ download_thumbnails () {
 	if [ "$thumbnail_quality" -eq 1 ]; then
 		image_download () {
 			# higher quality images
-			curl -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
+			@curl@ -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
 		}
 	else
 		image_download () {
- 			curl -s "$Url"  > "$thumb_dir/$Name.png"
+			@curl@ -s "$Url"  > "$thumb_dir/$Name.png"
 		}
 	fi

 	print_info "Downloading Thumbnails...\n"
 	thumb_urls=$(printf "%s" "$*" |\
-		jq  -r '.[]|[.thumbs,.videoID]|@tsv' )
+		@jq@  -r '.[]|[.thumbs,.videoID]|@tsv' )

 	while IFS=$tab_space read -r Url Name; do
-	    sleep 0.001
+	    @sleep@ 0.001
 		{
 			image_download
 		} &
@@ -628,7 +628,7 @@ get_sp_filter () {
 	#another example is sort by filter + upload date filter only changes one character as well
 	if [ -n "$filter_id" ]; then
 		#gets the character in the filter_id that needs to be replaced if upload_date_filter is also given
-		upload_date_character=$(printf "%s" "$filter_id" | awk '{print substr($1, 8, 1)}')
+		upload_date_character=$(printf "%s" "$filter_id" | @awk@ '{print substr($1, 8, 1)}')
 	fi

 	#For each of these, if upload_date_character is unset, the filter_id should be the normal filter
@@ -650,7 +650,7 @@ get_sp_filter () {
 	if [ -n "$upload_date_character" ]; then
 		#replaces the 8th character in the filter_id with the appropriate character
 		#the 8th character specifies the upload_date_filter
-		sp=$(printf "%s" "$filter_id" | sed 's/\(.\{7\}\)./\1'"$upload_date_character"'/')
+		sp=$(printf "%s" "$filter_id" | @sed@ 's/\(.\{7\}\)./\1'"$upload_date_character"'/')
 	#otherwise set it to the filter_id
 	else
 		sp=$filter_id
@@ -660,15 +660,15 @@ get_sp_filter () {

 get_yt_json () {
 	# scrapes the json embedded in the youtube html page
-	printf "%s" "$*" | sed -n '/var *ytInitialData/,$p' | tr -d '\n' |\
-        sed -E ' s_^.*var ytInitialData ?=__ ; s_;</script>.*__ ;'
+	printf "%s" "$*" | @sed@ -n '/var *ytInitialData/,$p' | @tr@ -d '\n' |\
+        @sed@ -E ' s_^.*var ytInitialData ?=__ ; s_;</script>.*__ ;'
 }

 get_yt_html () {
     link=$1
     query=$2
     printf "%s" "$(
-	curl "$link" -s \
+	@curl@ "$link" -s \
 	  -G --data-urlencode "search_query=$query" \
 	  -G --data-urlencode "sp=$sp" \
 	  -H 'Authority: www.youtube.com' \
@@ -684,7 +684,7 @@ get_video_data () {
 	# outputs tab and pipe separated fields: title, channel, view count, video length, video upload date, and the video id/url
 	# from the videos_json
 	printf "%s" "$*" |\
-	    jq -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
+	    @jq@ -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
 }

 scrape_channel () {
@@ -694,7 +694,7 @@ scrape_channel () {
 	channel_url=$*

 	# Converting channel title page url to channel video url
-	if ! printf "%s" "$channel_url" | grep -q '/videos *$'; then
+	if ! printf "%s" "$channel_url" | @grep@ -q '/videos *$'; then
 		channel_url=${channel_url%/featured}/videos
 	fi

@@ -706,8 +706,8 @@ scrape_channel () {
 	fi

 	#gets the channel name from title of page
-	channel_name=$(printf "%s" "$yt_html" | grep -o '<title>.*</title>' |
-		sed \
+	channel_name=$(printf "%s" "$yt_html" | @grep@ -o '<title>.*</title>' |
+		@sed@ \
 		-e 's/ - YouTube//' \
 		-e 's/<\/\?title>//g' \
 		-e "s/'/'/g" \
@@ -723,7 +723,7 @@ scrape_channel () {

 	#gets a list of videos
 	videos_json=$(printf "%s" "$yt_json" |\
-	jq '[ .contents | ..|.gridVideoRenderer? |
+	@jq@ '[ .contents | ..|.gridVideoRenderer? |
 	select(. !=null) |
 	    {
 	    	title: .title.runs[0].text,
@@ -736,7 +736,7 @@ scrape_channel () {
 	    }
 	]')

-	videos_json=$(printf "%s" "$videos_json" | jq '.[0:'$sub_link_count']')
+	videos_json=$(printf "%s" "$videos_json" | @jq@ '.[0:'$sub_link_count']')
 	printf "%s\n" "$videos_json" >> "$tmp_video_json_file"
 	#checks if it's empty in case it was defined in a config function eg: on_get_search
 	[ -z "$videos_data" ] && videos_data=$(get_video_data "$videos_json")
@@ -768,11 +768,11 @@ get_trending_url_data () {
 scrape_pt () {
      #gets a list of videos
      pt_json=$(
-     curl \
+     @curl@ \
          -s "https://sepiasearch.org/api/v1/search/videos" \
 	 -G --data-urlencode "search=$*")
      videos_json=$(printf "%s" "$pt_json" |\
-	jq '[ .data | .[] |
+	@jq@ '[ .data | .[] |
 	    {
 		title: .name,
 		channel: .channel.displayName,
@@ -829,7 +829,7 @@ scrape_yt () {
 	fi

 	#gets a list of videos
-	videos_json=$(printf "%s" "$yt_json" | jq '[ .contents|
+	videos_json=$(printf "%s" "$yt_json" | @jq@ '[ .contents|
 	..|.videoRenderer? |
 	select(. !=null) |
 		{
@@ -844,7 +844,7 @@ scrape_yt () {
 		}
 	]')

-	playlist_json=$(printf "%s" "$yt_json" | jq '[ .contents|
+	playlist_json=$(printf "%s" "$yt_json" | @jq@ '[ .contents|
 	..|.playlistRenderer? |
 	select(. !=null) |
 		{
@@ -904,28 +904,28 @@ get_search_query () {
 #> To select videos from videos_data
 user_selection () {
 	#remove subscription separators
-	videos_data_clean=$(printf "%s" "$videos_data" | sed "/.*$tab_space$/d")
+	videos_data_clean=$(printf "%s" "$videos_data" | @sed@ "/.*$tab_space$/d")

 	#$selected_data is the video the user picked
 	#picks the first n videos
 	if [ "$select_all" -eq 1 ] ; then
 		selected_data=$videos_data_clean
 	elif [ "$auto_select" -eq 1 ] ; then
-		selected_data=$(printf "%s\n" "$videos_data_clean" | sed "${link_count}"q )
+		selected_data=$(printf "%s\n" "$videos_data_clean" | @sed@ "${link_count}"q )
 	#picks n random videos
 	elif [ "$random_select" -eq 1 ] ; then
-	    selected_data=$(printf "%s\n" "$videos_data_clean" | posix_shuf | head -n${link_count})
+	    selected_data=$(printf "%s\n" "$videos_data_clean" | posix_shuf | @head@ -n${link_count})
 	    #posix_shuf, pick the first $link_count videos

 	#show thumbnail menu
 	elif [ "$show_thumbnails" -eq 1 ] ; then
-		dep_ck "ueberzug" "fzf"
+		dep_ck "@ueberzug@" "@fzf@"
 		export YTFZF_THUMB_DISP_METHOD="$thumb_disp_method"
 		[ "$thumb_disp_method" = "ueberzug" ] && start_ueberzug
 		#thumbnails only work in fzf, use fzf
-		menu_command="fzf -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
+		menu_command="@fzf@ -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
 		--nth=1,2 --expect='$shortcuts' $FZF_DEFAULT_OPTS \
-		--layout=reverse --preview \"sh $0 -U {}\" \
+		--layout=reverse --preview \"@sh@ $0 -U {}\" \
         	--preview-window \"$PREVIEW_SIDE:50%:noborder:wrap\""
 		selected_data=$( title_len=200 video_menu "$videos_data" )
 		[ "$thumb_disp_method" = "ueberzug" ] && stop_ueberzug
@@ -951,10 +951,10 @@ handle_shortcuts () {
     case $selected_key in
 	"$urls_shortcut") printf "%s\n" $selected_urls; return 1 ;;
 	"$title_shortcut")
-	    printf "%s\n" "$selected_data" | awk -F "  " '{print $1}'; return 1 ;;
+	    printf "%s\n" "$selected_data" | @awk@ -F "  " '{print $1}'; return 1 ;;
 	"$open_browser_shortcut")
 	    for url in $selected_urls; do
-		nohup $BROWSER "$url" >/dev/null 2>&1
+		@nohup@ $BROWSER "$url" >/dev/null 2>&1
 	    done
 	    return 1 ;;
 	"$watch_shortcut") is_download=0; is_audio_only=0; return 0;;
@@ -988,10 +988,10 @@ format_user_selection () {
 			11) selected_urls=$selected_urls$new_line'https://www.youtube.com/watch?v='$surl ;;
 			34) selected_urls=$selected_urls$new_line'https://www.youtube.com/playlist?list='$surl ;;
 			36)
-			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | jq '.[].url' | grep -F "$surl" | tr -d '"')" ;;
+			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | @jq@ '.[].url' | @grep@ -F "$surl" | @tr@ -d '"')" ;;
 			*) continue ;;
 		esac
-		refined_selected_data=$refined_selected_data$new_line$(printf '%s' "$videos_data" | grep "|$surl" )
+		refined_selected_data=$refined_selected_data$new_line$(printf '%s' "$videos_data" | @grep@ "|$surl" )
 	done<<-EOF
 	$selected_data
 	EOF
@@ -1014,9 +1014,9 @@ print_data () {
 get_video_format () {
 	# select format if flag given
 	[ $show_format -eq 0 ] && return
-        formats=$(youtube-dl -F "$(printf "$selected_urls")")
-        line_number=$(printf "$formats" | grep -n '.*extension  resolution.*' | cut -d: -f1)
-        quality=$(printf "$formats \n1 2 xAudio" | awk -v lineno=$line_number 'FNR > lineno {print $3}' | sort -n |  awk -F"x" '{print $2 "p"}' | uniq | sed -e "s/Audiop/Audio/" -e "/^p$/d" | eval "$menu_command" | sed "s/p//g")
+        formats=$(@youtube-dl@ -F "$(printf "$selected_urls")")
+        line_number=$(printf "$formats" | @grep@ -n '.*extension  resolution.*' | @cut@ -d: -f1)
+        quality=$(printf "$formats \n1 2 xAudio" | @awk@ -v lineno=$line_number 'FNR > lineno {print $3}' | @sort@ -n |  @awk@ -F"x" '{print $2 "p"}' | @uniq@ | @sed@ -e "s/Audiop/Audio/" -e "/^p$/d" | eval "$menu_command" | @sed@ "s/p//g")
 		[ -z "$quality"  ] && exit;
 		[ $quality = "Audio"  ] && video_pref= && video_player="$audio_player" || video_pref="bestvideo[height=?$quality][vcodec!=?vp9]+bestaudio/best"

@@ -1026,9 +1026,9 @@ get_video_format () {
 get_sub_lang () {
     if [ $auto_caption -eq 1 ]; then
         #Gets the auto generated subs and stores them in a file
-        sub_list=$(youtube-dl --list-subs  --write-auto-sub "$selected_urls" | sed '/Available subtitles/,$d' | awk '{print $1}' | sed '1d;2d;3d')
+        sub_list=$(@youtube-dl@ --list-subs  --write-auto-sub "$selected_urls" | @sed@ '/Available subtitles/,$d' | @awk@ '{print $1}' | @sed@ '1d;2d;3d')
         if [ -n "$sub_list" ]; then
-            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  youtube-dl  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
+            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  @youtube-dl@  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
         fi
 	unset sub_list
     fi
@@ -1046,10 +1046,10 @@ open_player () {
 	if [ $detach_player -eq 1 ]; then
 		if [ -z "$video_pref" ] || [ $is_audio_only -eq 1 ]; then
 			printf "Opening Player: %s\n" "$video_player $*"
-			setsid -f $video_player "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
+			@setsid@ -f $video_player "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
 		else
 			printf "Opening Player: %s\n" "$video_player_format$video_pref $*"
-			setsid -f $video_player_format"$video_pref"  "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
+			@setsid@ -f $video_player_format"$video_pref"  "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
 		fi
 		return
 	fi
@@ -1064,9 +1064,9 @@ open_player () {
 		fi
 	elif [ $is_download -eq 1 ]; then
 		if [ -z "$video_pref" ]; then
-			youtube-dl "$@"  "$YTFZF_SUBT_NAME"
+			@youtube-dl@ "$@"  "$YTFZF_SUBT_NAME"
 		else
-			youtube-dl -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
+			@youtube-dl@ -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
 		fi
 	fi
 }
@@ -1087,7 +1087,7 @@ play_url () {
 	fi

 	#Delete the temp auto-gen subtitle file
-	[ $auto_caption -eq 1 ] && rm -f "${YTFZF_SUBT_NAME#*=}"
+	[ $auto_caption -eq 1 ] && @rm@ -f "${YTFZF_SUBT_NAME#*=}"

 	unset player_urls
 }
@@ -1102,7 +1102,7 @@ session_is_running () {
 #> removes tmp files and clutter
 clean_up () {
 	if ! session_is_running ; then
-		[ -d "$thumb_dir" ] && rm -r "$thumb_dir"
+		[ -d  "$thumb_dir" ] && @rm@ -r "$thumb_dir"
 		: > "$pid_file"
 		function_exists "on_exit" && on_exit
 	fi
@@ -1124,9 +1124,9 @@ save_before_exit () {
 check_if_url () {
 	# to check if given input is a url
 	url_regex='^https\?://.*'
-	if printf "%s" "$1" | grep -q "$url_regex"; then
+	if printf "%s" "$1" | @grep@ -q "$url_regex"; then
 		is_url=1
-		selected_urls=$(printf "%s" "$1" | tr ' ' '\n')
+		selected_urls=$(printf "%s" "$1" | @tr@ ' ' '\n')
 		scrape="url"
 	else
 		is_url=0
@@ -1139,10 +1139,10 @@ get_history () {
 	if [ "$enable_hist" -eq 1 ]; then
 		[ -e "$history_file" ] || : > "$history_file"
 		#gets history data in reverse order (makes it most recent to least recent)
-		hist_data=$( sed '1!G; h; $!d' "$history_file" )
+		hist_data=$( @sed@ '1!G; h; $!d' "$history_file" )
 		[ -z "$hist_data" ] && printf "History is empty!\n" >&2 && return 1;
 		#removes duplicate values from $history_data
-		videos_data=$(printf "%s" "$hist_data" | uniq )
+		videos_data=$(printf "%s" "$hist_data" | @uniq@ )
 		[ "$sort_videos_data" -eq 1 ] && videos_data="$(printf "%s" "$videos_data"  | sort_video_data_fn)"
 	else
 		printf "History is not enabled. Please enable it to use this option (-H).\n" >&2;
@@ -1177,10 +1177,10 @@ get_search_history () {
 	if [ "$enable_search_hist" -eq 1 ]; then
 		[ -e "$search_history_file" ] || : > "$search_history_file"
 		#gets history data in reverse order (makes it most recent to least recent)
-		hist_data=$( sed '1!G; h; $!d' "$search_history_file" )
+		hist_data=$( @sed@ '1!G; h; $!d' "$search_history_file" )
 		[ -z "$hist_data" ] && printf "Search history is empty!\n" >&2 && return 1;
 		#removes duplicate values from $history_data
-		search_history=$(printf "%s" "$hist_data" | uniq )
+		search_history=$(printf "%s" "$hist_data" | @uniq@ )
 	else
 		printf "Search history is not enabled. Please enable it to use this option (-q).\n" >&2;
 		exit 1;
@@ -1190,7 +1190,7 @@ get_search_history () {

 set_search_history () {
     [ -z "$search_query" ] && return
-    [ $enable_search_hist -eq 1 ] && printf "%s\t%s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$search_query" >> "$search_history_file" ;
+    [ $enable_search_hist -eq 1 ] && printf "%s\t%s\n" "$(@date@ '+%Y-%m-%d %H:%M:%S')" "$search_query" >> "$search_history_file" ;
 }

 search_history_menu () {
@@ -1200,15 +1200,15 @@ search_history_menu () {
     #when using an external menu, the search history will be done there
         choice=$( printf "%s\n" "$search_history" | eval "$external_menu" )
     else
-        choice="$( printf "%s\n" "$search_history" | fzf --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
+        choice="$( printf "%s\n" "$search_history" | @fzf@ --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
     fi

     # first line is the fzf query (what the user types in fzf)
     # second line is the fzf --expect key pressed
     # third line is the search_history selection made
-    query="$( printf "%s" "$choice" | sed -n '1p' )"
-    key="$( printf "%s" "$choice" | sed -n '2p' )"
-    selection="$( printf "%s" "$choice" | sed -n '3p' )"
+    query="$( printf "%s" "$choice" | @sed@ -n '1p' )"
+    key="$( printf "%s" "$choice" | @sed@ -n '2p' )"
+    selection="$( printf "%s" "$choice" | @sed@ -n '3p' )"

     # if no search history selection has been made
     # and the user typed a query, use that instead
@@ -1225,7 +1225,7 @@ search_history_menu () {
             search_query="$query"
             return;;
     esac
-    search_query="$( printf "%s" "$selection" | awk -F'\t' '{printf "%s", $NF}' )"
+    search_query="$( printf "%s" "$selection" | @awk@ -F'\t' '{printf "%s", $NF}' )"
 }

 ! function_exists "send_select_video_notif" && send_select_video_notif () {
@@ -1244,13 +1244,13 @@ search_history_menu () {

 	#if downloading, say Downloading not currently playing
 	[ $is_download -eq 1 ] && title="Downloading" || title="Currently playing"
-	notify-send "$title" "$message" -i "$video_thumb"
+	@notify-send@ "$title" "$message" -i "$video_thumb"

 	unset message video_thumb title
 }

 send_notify () {
-	videos_selected_count=$(printf "%s\n" "$*" | wc -l)
+	videos_selected_count=$(printf "%s\n" "$*" | @wc@ -l)
 	while IFS=$tab_space read -r video_title video_channel video_views video_duration video_date video_shorturl; do
 	    send_select_video_notif
 	done << EOF
@@ -1284,14 +1284,14 @@ if ! function_exists "data_sort_key"; then
 	sort_by="${5#|}"
 	sort_by="${sort_by#Streamed}"
 	#print the data that should be sorted by
-	printf "%d" "$(date -d "${sort_by}" '+%s')"
+	printf "%d" "$(@date@ -d "${sort_by}" '+%s')"
 	unset sort_by
     }
 fi
 #the function to use for sorting
 if ! function_exists "data_sort_fn"; then
     data_sort_fn () {
-	sort -nr
+	@sort@ -nr
     }
 fi
 sort_video_data_fn () {
@@ -1300,7 +1300,7 @@ sort_video_data_fn () {
 		IFS="$tab_space"
 		#run the key function to get the value to sort by
 		printf "%s\t%s\n" "$(data_sort_key $line)" "$line"
-	done | data_sort_fn | cut -f2-
+	done | data_sort_fn | @cut@ -f2-
 	unset IFS line
 }

@@ -1314,19 +1314,19 @@ scrape_subscriptions () {
 	while IFS= read -r url; do
 		scrape_channel "$url" &
 	done <<-EOF
-	$( sed \
+	$( @sed@ \
 	-e "s/#.*//" \
 	-e "/^[[:space:]]*$/d" \
 	-e "s/[[:space:]]*//g" \
 	"$subscriptions_file")
 	EOF
 	wait
-	videos_json="$(cat "$tmp_video_json_file")"
+	videos_json="$(@cat@ "$tmp_video_json_file")"
 	export videos_json
 	if [ $sort_videos_data -eq 1 ]; then
 		videos_data=$(sort_video_data_fn < "$tmp_video_data_file")
 	else
-		videos_data=$(cat "$tmp_video_data_file")
+		videos_data=$(@cat@ "$tmp_video_data_file")
 	fi
 }

@@ -1346,11 +1346,11 @@ create_subs () {
     : > "$config_dir/subscriptions"

     # check how many subscriptions there are in the file
-    sublength=$( jq '. | length' < "$yt_sub_import_file" )
+    sublength=$( @jq@ '. | length' < "$yt_sub_import_file" )

-    for i in $(seq $((sublength - 1))); do
-        channelInfo=$(jq --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
-	printf "%s\n" "$(printf "%s" "$channelInfo" | tr -d '[]"\n,')" >> "$subscriptions_file"
+    for i in $(@seq@ $((sublength - 1))); do
+        channelInfo=$(@jq@ --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
+	printf "%s\n" "$(printf "%s" "$channelInfo" | @tr@ -d '[]"\n,')" >> "$subscriptions_file"
     done
     exit
 }
@@ -1367,10 +1367,10 @@ verify_thumb_disp_method () {

 #sort -R is not posix
 posix_shuf () {
-    awk -F '\n' '
+    @awk@ -F '\n' '
 	BEGIN {srand()} #set the random seed at the start
 	{print rand() " " $0} #prepend a random number for each line' |\
-    sort | sed -E 's/[^ ]* //'
+    @sort@ | @sed@ -E 's/[^ ]* //'
     #sort by the random numbers, remove the random number
 }

@@ -1486,8 +1486,8 @@ parse_opt () {
 			exit ;;
 		version)
 			printf "\033[1mytfzf:\033[0m %s\n" "$YTFZF_VERSION"
-			printf "\033[1myoutube-dl:\033[0m %s\n" "$(youtube-dl --version)"
-			command -v "fzf" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(fzf --version)"
+			printf "\033[1myoutube-dl:\033[0m %s\n" "$(@youtube-dl@ --version)"
+			command -v "@fzf@" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(@fzf@ --version)"
 			exit ;;

 		subt)
@@ -1559,19 +1559,19 @@ done
 shift $((OPTIND-1))

 #only apply to ext_menu since they dont have a terminal to print to
-[ $is_ext_menu -eq 1 ] && command -v notify-send 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0
+[ $is_ext_menu -eq 1 ] && command -v @notify-send@ 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0

 #used for thumbnail previews in ueberzug
 if [ $is_ext_menu -eq 0 ]; then
-	export TTY_LINES=$(tput lines)
- 	export TTY_COLS=$(tput cols)
+	export TTY_LINES=$(@tput@ lines)
+	export TTY_COLS=$(@tput@ cols)
 fi

 #if both are true, it defaults to using fzf, and if fzf isnt installed it will throw an error
 #so print this error instead and set $show_thumbnails to 0
 if [ $is_ext_menu -eq 1 ] && [ $show_thumbnails -eq 1 ]; then
 	[ $ext_menu_notifs -eq 1 ] &&\
-	    notify-send "warning" "Currently thumbnails do not work in external menus" ||\
+	    @notify-send@ "warning" "Currently thumbnails do not work in external menus" ||\
 	    printf "\033[33mWARNING: Currently thumbnails do not work in external menus\033[0m\n" >&2
 	show_thumbnails=0
 fi
--
2.32.0


code:
From ceb6836cd31653267506957cd0ccf78046404d3b Mon Sep 17 00:00:00 2001
From: Raghav Gururajan <rg@raghavgururajan.name>
Date: Mon, 5 Jul 2021 06:47:38 -0400
Subject: [PATCH 2/2] Disable updates within the application.

Patch the code responsible for self-updating the application.

Co-authored-by: jgart <jgart@dismail.de>
---
 ytfzf | 18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/ytfzf b/ytfzf
index f0f2e16..2d1bb2e 100755
--- a/ytfzf
+++ b/ytfzf
@@ -1260,22 +1260,8 @@ EOF
 }

 update_ytfzf () {
-	branch="$1"
-	updatefile="/tmp/ytfzf-update"
-	curl -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
-
-	if sed -n '1p' < "$updatefile" | grep -q '#!/bin/sh'; then
-		chmod 755 "$updatefile"
-		[ "$(uname)" = "Darwin" ] && prefix="/usr/local/bin" || prefix="/usr/bin"
-		function_exists "sudo" && doasroot="sudo" || doasroot="doas"
-		$doasroot cp "$updatefile" "$prefix/ytfzf"
-		unset prefix doasroot
-	else
-		printf "%bFailed to update ytfzf. Try again later.%b" "$c_red" "$c_reset"
-	fi
-
-	rm "$updatefile"
-	exit 0
+       printf "%bUpdates have to be installed with Guix.%b\n" "$c_red" "$c_reset"
+       exit 1
 }

 #gives a value to sort by (this will give the unix time the video was uploaded)
--
2.32.0


code:
From f2380a53fb84d370eaf6e6c3473062c54c57fac7 Mon Sep 17 00:00:00 2001
From: Oliver Giles <ohw.giles@gmail.com>
Date: Mon, 1 Feb 2021 10:12:16 +1300
Subject: [PATCH] Prevent potential double-free in TNEFSubjectHandler

If TNEFSubjectHandler is called multiple times, but the last time
failed due to the PREALLOCCHECK, the subject.data member will be
a freed, but invalid pointer. To prevent a double-free next time
TNEFSubjectHandler is entered, set it to zero after freeing.

Resolves: #85
Reported-by: jasperla
---
 lib/ytnef.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/ytnef.c b/lib/ytnef.c
index b148719..b06c807 100644
--- a/lib/ytnef.c
+++ b/lib/ytnef.c
@@ -301,8 +301,10 @@ int TNEFFromHandler STD_ARGLIST {
 }
 // -----------------------------------------------------------------------------
 int TNEFSubjectHandler STD_ARGLIST {
-  if (TNEF->subject.data)
+  if (TNEF->subject.data) {
     free(TNEF->subject.data);
+    TNEF->subject.data = NULL;
+  }

   PREALLOCCHECK(size, 100);
   TNEF->subject.data = calloc(size+1, sizeof(BYTE));


code:
From f9ff4a203b8c155d51a208cadadb62f224fba715 Mon Sep 17 00:00:00 2001
From: Oliver Giles <ohw.giles@gmail.com>
Date: Mon, 1 Feb 2021 10:18:17 +1300
Subject: [PATCH] Ensure the size of the version field is 4 bytes

A corrupted version field size can cause TNEFVersion to access outside
of allocated memory. Check the version is the expected size and raise
an error if not.

Resolves: #86
Reported-by: jasperla
---
 lib/ytnef.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/ytnef.c b/lib/ytnef.c
index b148719..ffede44 100644
--- a/lib/ytnef.c
+++ b/lib/ytnef.c
@@ -335,6 +335,10 @@ int TNEFRendData STD_ARGLIST {
 int TNEFVersion STD_ARGLIST {
   WORD major;
   WORD minor;
+  if (size != 2 * sizeof(WORD)) {
+    printf("Incorrect size of version field, suspected corruption\n");
+    return -1;
+  }
   minor = SwapWord((BYTE*)data, size);
   major = SwapWord((BYTE*)data + 2, size - 2);


code:
Description: fix race condition allowing attackers to access destination file
 This commit addresses https://github.com/facebook/zstd/issues/2491.
 .
 Note that a downside of this solution is that it is global: `umask()` affects
 all file creation calls in the process. I believe this is safe since
 `fileio.c` functions should only ever be used in the zstd binary, and these
 are (almost) the only files ever created by zstd, and AIUI they're only
 created in a single thread. So we can get away with messing with global state.
 .
 Note that this doesn't change the permissions of files created by `dibio.c`.
 I'm not sure what those should be...
Author: W. Felix Handte <w@felixhandte.com>
Origin: upstream
Bug: https://github.com/facebook/zstd/issues/2491
Bug-Debian: https://github.com/facebook/zstd/issues/2491
Applied-Upstream: commit:a774c5797399040af62db21d8a9b9769e005430e
Reviewed-by: Étienne Mollier <etienne.mollier@mailoo.org>
Last-Update: 2021-03-03
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/programs/fileio.c
+++ b/programs/fileio.c
@@ -606,11 +606,11 @@ FIO_openDstFile(FIO_prefs_t* const prefs
             FIO_remove(dstFileName);
     }   }

-    {   FILE* const f = fopen( dstFileName, "wb" );
+    {   const int old_umask = UTIL_umask(0177); /* u-x,go-rwx */
+        FILE* const f = fopen( dstFileName, "wb" );
+        UTIL_umask(old_umask);
         if (f == NULL) {
             DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno));
-        } else if(srcFileName != NULL && strcmp (srcFileName, stdinmark)) {
-            chmod(dstFileName, 00600);
         }
         return f;
     }
--- a/programs/util.c
+++ b/programs/util.c
@@ -54,6 +54,15 @@ int UTIL_getFileStat(const char* infilen
     return 1;
 }

+int UTIL_umask(int mode) {
+#if PLATFORM_POSIX_VERSION > 0
+    return umask(mode);
+#else
+    /* do nothing, fake return value */
+    return mode;
+#endif
+}
+
 int UTIL_setFileStat(const char *filename, stat_t *statbuf)
 {
     int res = 0;
--- a/programs/util.h
+++ b/programs/util.h
@@ -136,6 +136,10 @@ int UTIL_isSameFile(const char* file1, c
 int UTIL_compareStr(const void *p1, const void *p2);
 int UTIL_isCompressedFile(const char* infilename, const char *extensionList[]);
 const char* UTIL_getFileExtension(const char* infilename);
+/**
+ * Wraps umask(). Does nothing when the platform doesn't have that concept.
+ */
+int UTIL_umask(int mode);

 #ifndef _MSC_VER
 U32 UTIL_isFIFO(const char* infilename);


code:
The following 3 patches applied to 0.13.69 in this order, combined:
https://github.com/gdraheim/zziplib/commit/9411bde3e4a70a81ff3ffd256b71927b2d90dcbb.patch
https://github.com/gdraheim/zziplib/commit/d2e5d5c53212e54a97ad64b793a4389193fec687.patch
https://github.com/gdraheim/zziplib/commit/0e1dadb05c1473b9df2d7b8f298dab801778ef99.patch

diff --git a/test/test.zip b/test/test.zip
index 2c992ea..952d475 100644
Binary files a/test/test.zip and b/test/test.zip differ
diff --git a/zzip/zip.c b/zzip/zip.c
index 14e2e06..f97a40a 100644
--- a/zzip/zip.c
+++ b/zzip/zip.c
@@ -472,9 +472,15 @@ __zzip_parse_root_directory(int fd,
         } else
         {
             if (io->fd.seeks(fd, zz_rootseek + zz_offset, SEEK_SET) < 0)
+	    {
+	    	free(hdr0);
                 return ZZIP_DIR_SEEK;
+	    }
             if (io->fd.read(fd, &dirent, sizeof(dirent)) < __sizeof(dirent))
+	    {
+	    	free(hdr0);
                 return ZZIP_DIR_READ;
+	    }
             d = &dirent;
         }

@@ -574,11 +580,18 @@ __zzip_parse_root_directory(int fd,

         if (hdr_return)
             *hdr_return = hdr0;
+	else
+	{
+	    /* If it is not assigned to *hdr_return, it will never be free()'d */
+	    free(hdr0);
+	}
     }                           /* else zero (sane) entries */
+    else
+        free(hdr0);
 #  ifndef ZZIP_ALLOW_MODULO_ENTRIES
-    return (entries != zz_entries ? ZZIP_CORRUPTED : 0);
+    return (entries != zz_entries) ? ZZIP_CORRUPTED : 0;
 #  else
-    return ((entries & (unsigned)0xFFFF) != zz_entries ? ZZIP_CORRUPTED : 0);
+    return ((entries & (unsigned)0xFFFF) != zz_entries) ? ZZIP_CORRUPTED : 0;
 #  endif
 }


code:
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014, 2018 Eric Bavier <bavier@member.fsf.org>
;;; Copyright © 2015, 2018 Leo Famulari <leo@famulari.name>
;;; Copyright © 2018–2021 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2019 Christopher Baines <mail@cbaines.net>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu packages patchutils)
  #:use-module (guix utils)
  #:use-module (guix packages)
  #:use-module (guix licenses)
  #:use-module (guix download)
  #:use-module (guix git-download)
  #:use-module (guix build-system gnu)
  #:use-module (guix build-system python)
  #:use-module (gnu packages)
  #:use-module (gnu packages ed)
  #:use-module (gnu packages base)
  #:use-module (gnu packages bash)
  #:use-module (gnu packages check)
  #:use-module (gnu packages databases)
  #:use-module (gnu packages django)
  #:use-module (gnu packages file)
  #:use-module (gnu packages gawk)
  #:use-module (gnu packages gettext)
  #:use-module (gnu packages glib)
  #:use-module (gnu packages gnome)
  #:use-module (gnu packages gtk)
  #:use-module (gnu packages less)
  #:use-module (gnu packages mail)
  #:use-module (gnu packages ncurses)
  #:use-module (gnu packages perl)
  #:use-module (gnu packages python)
  #:use-module (gnu packages python-xyz)
  #:use-module (gnu packages version-control)
  #:use-module (gnu packages xml))

(define-public patchutils
  (package
    (name "patchutils")
    (version "0.3.4")
    (source
     (origin
      (method url-fetch)
      (uri (string-append "http://cyberelk.net/tim/data/patchutils/stable/"
                          name "-" version ".tar.xz"))
      (sha256
       (base32
        "0xp8mcfyi5nmb5a2zi5ibmyshxkb1zv1dgmnyn413m7ahgdx8mfg"))
      (patches (search-patches "patchutils-test-perms.patch"))))
    (build-system gnu-build-system)
    (inputs `(("perl" ,perl)))
    (arguments
     '(#:parallel-tests? #f
       #:phases
       (modify-phases %standard-phases
         (add-before 'check 'patch-test-scripts
           (lambda _
             (substitute* (find-files "tests" "^run-test$")
               (("/bin/echo") (which "echo")))
             #t))
         (add-after 'install 'wrap-program
           ;; Point installed scripts to the utilities they need.
           (lambda* (#:key inputs outputs #:allow-other-keys)
             (let* ((out       (assoc-ref outputs "out"))
                    (diffutils (assoc-ref inputs "diffutils"))
                    (sed       (assoc-ref inputs "sed"))
                    (gawk      (assoc-ref inputs "gawk")))
               (for-each
                (lambda (prog)
                  (wrap-program (string-append out "/bin/" prog)
                    `("PATH" ":" prefix
                      ,(map (lambda (dir)
                              (string-append dir "/bin"))
                            (list diffutils sed gawk)))))
                '("dehtmldiff" "editdiff" "espdiff")))
             #t)))))
    (home-page "http://cyberelk.net/tim/software/patchutils")
    (synopsis "Collection of tools for manipulating patch files")
    (description
     "Patchutils is a collection of programs that can manipulate patch files
in useful ways such as interpolating between two pre-patches, combining two
incremental patches, fixing line numbers in hand-edited patches, and simply
listing the files modified by a patch.")
    (license gpl2+)))

(define-public quilt
  (package
    (name "quilt")
    (version "0.66")
    (source
     (origin
       (method url-fetch)
       (uri (string-append "mirror://savannah/quilt/"
                           "quilt-" version ".tar.gz"))
       (sha256
        (base32 "01vfvk4pqigahx82fhaaffg921ivd3k7rylz1yfvy4zbdyd32jri"))))
    (build-system gnu-build-system)
    (native-inputs
     `(("gettext" ,gettext-minimal)))
    (inputs `(("perl" ,perl)
              ("less" ,less)
              ("file" ,file)
              ("ed" ,ed)
              ("diffstat" ,diffstat)))
    (arguments
     '(#:parallel-tests? #f
       #:phases
       (modify-phases %standard-phases
         (add-before 'check 'patch-tests
           (lambda _
             (substitute*
                 '("test/run"
                   "test/edit.test")
               (("/bin/sh") (which "sh")))
             #t))
         (add-after 'install 'wrap-program
           ;; quilt's configure checks for the absolute path to the utilities it
           ;; needs, but uses only the name when invoking them, so we need to
           ;; make sure the quilt script can find those utilities when run.
           (lambda* (#:key inputs outputs #:allow-other-keys)
             (let* ((out       (assoc-ref outputs "out"))
                    (coreutils (assoc-ref inputs "coreutils"))
                    (diffutils (assoc-ref inputs "diffutils"))
                    (findutils (assoc-ref inputs "findutils"))
                    (diffstat  (assoc-ref inputs "diffstat"))
                    (less      (assoc-ref inputs "less"))
                    (file      (assoc-ref inputs "file"))
                    (ed        (assoc-ref inputs "ed"))
                    (sed       (assoc-ref inputs "sed"))
                    (bash      (assoc-ref inputs "bash"))
                    (grep      (assoc-ref inputs "grep")))
               (wrap-program (string-append out "/bin/quilt")
                 `("PATH" ":" prefix
                   ,(map (lambda (dir)
                           (string-append dir "/bin"))
                         (list coreutils diffutils findutils
                               less file ed sed bash grep
                               diffstat)))))
             #t)))))
    (home-page "https://savannah.nongnu.org/projects/quilt/")
    (synopsis "Script for managing patches to software")
    (description
     "Quilt allows you to easily manage large numbers of patches by keeping
track of the changes each patch makes.  Patches can be applied, un-applied,
refreshed, and more.")
    (license gpl2)))

(define-public colordiff
  (package
    (name "colordiff")
    (version "1.0.19")
    (source
      (origin
        (method url-fetch)
        (uri (list (string-append "https://www.colordiff.org/colordiff-"
                                  version ".tar.gz")
                   (string-append "http://www.colordiff.org/archive/colordiff-"
                                  version ".tar.gz")))
      (sha256
       (base32 "069vzzgs7b44bmfh3ks2psrdb26s1w19gp9w4xxbgi7nhx6w3s26"))))
    (build-system gnu-build-system)
    (arguments
     `(#:tests? #f                      ; no tests
       #:make-flags (list (string-append "DESTDIR=" (assoc-ref %outputs "out"))
                          "INSTALL_DIR=/bin" "MAN_DIR=/share/man/man1")
       #:phases
       (modify-phases %standard-phases
         (delete 'configure)            ; no configure script
         (delete 'build))))             ; nothing to build
    (inputs
     `(("perl" ,perl)
       ("xmlto" ,xmlto)))
    (home-page "https://www.colordiff.org")
    (synopsis "Display diff output with colors")
    (description
     "Colordiff is Perl script wrapper on top of diff command which provides
'syntax highlighting' for various patch formats.")
    (license gpl2+)))

(define-public patches
  (let ((commit "ef1b8a7d954b82ed4af3a08fd63d2085d19090ef"))
    (package
      (name "patches")
      (home-page "https://github.com/stefanha/patches")
      (version (string-append "0.0-1." (string-take commit 7)))
      (source (origin
                (method git-fetch)
                (uri (git-reference
                      (url home-page)
                      (commit commit)))
                (sha256
                 (base32
                  "11rdmhv0l1s8nqb20ywmw2zqizczch2p62qf9apyx5wqgxlnjshk"))
                (file-name (string-append name "-"version "-checkout"))))
      (build-system python-build-system)
      (inputs `(("python-notmuch" ,python2-notmuch)))
      (arguments
       `(#:tests? #f                             ;no "test" target
         #:python ,python-2))                    ;not compatible with Python 3
      (synopsis "Patch tracking tool")
      (description
       "@code{Patches} is a patch-tracking tool initially written for the QEMU
project.  It provides commands that build a database of patches from a mailing
list, and commands that can search that database.  It allows users to track
the status of a patch, apply patches, and search for patches---all that from
the command-line or from Emacs via its Notmuch integration.")
      (license gpl2+))))

(define-public vbindiff
  (package
    (name "vbindiff")
    (version "3.0_beta5")
    (source (origin
              (method url-fetch)
              (uri (string-append "https://www.cjmweb.net/vbindiff/vbindiff-"
                                  version ".tar.gz"))
              (sha256
               (base32
                "1f1kj4jki08bnrwpzi663mjfkrx4wnfpzdfwd2qgijlkx5ysjkgh"))))
    (build-system gnu-build-system)
    (inputs
     `(("ncurses" ,ncurses)))
    (home-page "https://www.cjmweb.net/vbindiff/")
    (synopsis "Console-based tool for comparing binary data")
    (description "Visual Binary Diff (@command{vbindiff}) displays files in
hexadecimal and ASCII (or EBCDIC).  It can also display two files at once, and
highlight the differences between them.  It works well with large files (up to 4
GiB).")
    (license gpl2+)))

(define-public meld
  (package
    (name "meld")
    (version "3.20.3")
    (source
     (origin
       (method url-fetch)
       (uri (string-append "mirror://gnome/sources/meld/"
                           (version-major+minor version)
                           "/meld-" version ".tar.xz"))
       (sha256
        (base32 "06h52vaghvj5n507mj0hhk9yrca16pyl4l16c00b3bmkplljpqzh"))))
    (build-system python-build-system)
    (native-inputs
     `(("intltool" ,intltool)
       ("xmllint" ,libxml2)
       ("glib-compile-schemas" ,glib "bin")
       ("python-pytest" ,python-pytest)))
    (inputs
     `(("python-cairo" ,python-pycairo)
       ("python-gobject" ,python-pygobject)
       ("gsettings-desktop-schemas" ,gsettings-desktop-schemas)
       ("gtksourceview" ,gtksourceview-3)))
    (propagated-inputs
     `(("dconf" ,dconf)))
    (arguments
     `(#:imported-modules ((guix build glib-or-gtk-build-system)
                           ,@%python-build-system-modules)
       #:modules ((guix build python-build-system)
                  ((guix build glib-or-gtk-build-system) #:prefix glib-or-gtk:)
                  (guix build utils))
       #:phases
       (modify-phases %standard-phases
         ;; This setup.py script does not support one of the Python build
         ;; system's default flags, "--single-version-externally-managed".
         (replace 'install
           (lambda* (#:key outputs #:allow-other-keys)
             (invoke "python" "setup.py"
                     ;; This setup.py runs gtk-update-icon-cache  which we don't want.
                     "--no-update-icon-cache"
                     ;; "--no-compile-schemas"
                     "install"
                     (string-append "--prefix=" (assoc-ref outputs "out"))
                     "--root=/")))
         ;; The tests need to be run after installation.
         (delete 'check)
         (add-after 'install 'check
           (lambda* (#:key inputs outputs #:allow-other-keys)
             ;; Tests look for installed package
             (add-installed-pythonpath inputs outputs)
             ;; The tests fail when HOME=/homeless-shelter.
             (setenv "HOME" "/tmp")
             (invoke "py.test" "-v" "-k"
                     ;; TODO: Those tests fail, why?
                     "not test_classify_change_actions")))
         (add-after 'wrap 'glib-or-gtk-wrap
           (assoc-ref glib-or-gtk:%standard-phases 'glib-or-gtk-wrap))
         (add-after 'wrap 'wrap-typelib
           (lambda* (#:key inputs outputs #:allow-other-keys)
             (let ((out (assoc-ref outputs "out")))
               (wrap-program (string-append out "/bin/meld")
                 `("GI_TYPELIB_PATH" prefix
                   ,(search-path-as-string->list (getenv "GI_TYPELIB_PATH"))))
               #t))))))
    (home-page "https://meldmerge.org/")
    (synopsis "Compare files, directories and working copies")
    (description "Meld is a visual diff and merge tool targeted at
developers.  Meld helps you compare files, directories, and version controlled
projects.  It provides two- and three-way comparison of both files and
directories, and has support for many popular version control systems.

Meld helps you review code changes and understand patches.  It might even help
you to figure out what is going on in that merge you keep avoiding.")
    (license gpl2)))

(define-public patchwork
  (package
    (name "patchwork")
    (version "3.0.1")
    (source (origin
              (method git-fetch)
              (uri (git-reference
                    (url "https://github.com/getpatchwork/patchwork")
                    (commit (string-append "v" version))))
              (file-name (git-file-name name version))
              (sha256
               (base32
                "049ih1fbbbmj11v5m9ilahifl8x7gi6wyba58552y9n9djzs8csc"))))
    (build-system python-build-system)
    (arguments
     `(;; TODO: Tests require a running database
       #:tests? #f
       #:phases
       (modify-phases %standard-phases
         (delete 'configure)
         (delete 'build)
         (add-after 'unpack 'replace-wsgi.py
           (lambda* (#:key inputs outputs #:allow-other-keys)
             (delete-file "patchwork/wsgi.py")
             (call-with-output-file "patchwork/wsgi.py"
               (lambda (port)
                 ;; Embed the PYTHONPATH containing the dependencies, as well
                 ;; as the python modules in this package in the wsgi.py file,
                 ;; as this will ensure they are available at runtime.
                 (define pythonpath
                   (string-append (getenv "PYTHONPATH")
                                  ":"
                                  (site-packages inputs outputs)))
                 (display
                  (string-append "
import os, sys

sys.path.extend('" pythonpath "'.split(':'))

from django.core.wsgi import get_wsgi_application

# By default, assume that patchwork is running as a Guix service, which
# provides the settings as the 'guix.patchwork.settings' Python module.
#
# When using httpd, it's hard to set environment variables, so rely on the
# default set here.
os.environ['DJANGO_SETTINGS_MODULE'] = os.getenv(
  'DJANGO_SETTINGS_MODULE',
  'guix.patchwork.settings' # default
)

application = get_wsgi_application()\n") port)))))
         (replace 'check
           (lambda* (#:key tests? #:allow-other-keys)
             (when tests?
               (setenv "DJANGO_SETTINGS_MODULE" "patchwork.settings.dev")
               (invoke "python" "-Wonce" "./manage.py" "test" "--noinput"))
             #t))
         (replace 'install
           (lambda* (#:key inputs outputs #:allow-other-keys)
             (let ((out (assoc-ref outputs "out"))
                   (out-site-packages (site-packages inputs outputs)))
               (for-each (lambda (directory)
                           (copy-recursively
                            directory
                            (string-append out-site-packages directory)))
                         '(;; Contains the python code
                           "patchwork"
                           ;; Contains the templates for the generated HTML
                           "templates"))
               (delete-file-recursively
                (string-append out-site-packages "patchwork/tests"))

               ;; Install patchwork related tools
               (for-each (lambda (file)
                           (install-file file (string-append out "/bin")))
                         (list
                          (string-append out-site-packages
                                         "patchwork/bin/parsemail.sh")
                          (string-append out-site-packages
                                         "patchwork/bin/parsemail-batch.sh")))

               ;; Collect the static assets, this includes JavaScript, CSS and
               ;; fonts. This is a standard Django process when running a
               ;; Django application for regular use, and includes assets for
               ;; dependencies like the admin site from Django.
               ;;
               ;; The intent here is that you can serve files from this
               ;; directory through a webserver, which is recommended when
               ;; running Django applications.
               (let ((static-root
                      (string-append out "/share/patchwork/htdocs")))
                 (mkdir-p static-root)
                 (copy-file "patchwork/settings/production.example.py"
                            "patchwork/settings/assets.py")
                 (setenv "DJANGO_SECRET_KEY" "dummyvalue")
                 (setenv "DJANGO_SETTINGS_MODULE" "patchwork.settings.assets")
                 (setenv "STATIC_ROOT" static-root)
                 (invoke "./manage.py" "collectstatic" "--no-input"))

               ;; The lib directory includes example configuration files that
               ;; may be useful when deploying patchwork.
               (copy-recursively "lib"
                                 (string-append
                                  out "/share/doc/" ,name "-" ,version)))
             #t))
         ;; The hasher script is used from the post-receive.hook
         (add-after 'install 'install-hasher
           (lambda* (#:key inputs outputs #:allow-other-keys)
             (let* ((out (assoc-ref outputs "out"))
                    (out-site-packages (site-packages inputs outputs))
                    (out-hasher.py (string-append out-site-packages
                                                  "/patchwork/hasher.py")))
               (chmod out-hasher.py #o555)
               (symlink out-hasher.py (string-append out "/bin/hasher")))
             #t))
         ;; Create a patchwork specific version of Django's command line admin
         ;; utility.
         (add-after 'install 'install-patchwork-admin
           (lambda* (#:key inputs outputs #:allow-other-keys)
             (let* ((out (assoc-ref outputs "out")))
               (mkdir-p (string-append out "/bin"))
               (call-with-output-file (string-append out "/bin/patchwork-admin")
                 (lambda (port)
                   (simple-format port "#!~A
import os, sys

if __name__ == \"__main__\":
    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)" (which "python"))))
               (chmod (string-append out "/bin/patchwork-admin") #o555))
             #t)))))
    (inputs
     `(("python-wrapper" ,python-wrapper)))
    (propagated-inputs
     `(("python-django" ,python-django-2.2)
       ;; TODO: Make this configurable
       ("python-psycopg2" ,python-psycopg2)
       ("python-mysqlclient" ,python-mysqlclient)
       ("python-django-filter" ,python-django-filter)
       ("python-djangorestframework" ,python-djangorestframework)
       ("python-django-debug-toolbar" ,python-django-debug-toolbar)))
    (synopsis "Web based patch tracking system")
    (description
     "Patchwork is a patch tracking system.  It takes in emails containing
patches, and displays the patches along with comments and state information.
Users can login allowing them to change the state of patches.")
    (home-page "http://jk.ozlabs.org/projects/patchwork/")
    (license gpl2+)))

(define-public pwclient
  (package
    (name "pwclient")
    (version "1.3.0")
    (source (origin
              (method git-fetch)
              (uri (git-reference
                    (url "https://github.com/getpatchwork/pwclient")
                    (commit version)))
              (file-name (git-file-name name version))
              (sha256
               (base32
                "1xckwvcqklzpyh3xs4k2zm40ifp0q5fdkj2vmgb8vhfvl1ivs6jv"))))
    (build-system python-build-system)
    (arguments
     `(#:phases
       (modify-phases %standard-phases
         (add-after 'unpack 'patch-requirements
           (lambda _
             (substitute* "test-requirements.txt"
               ;; The pytest requirement is unnecessarily strict
               (("pytest>=3.0,<5.0;")
                "pytest>=3.0,<6.0;"))
             #t))
         (add-before 'build 'set-PBR_VERSION
           (lambda _
             (setenv "PBR_VERSION"
                     ,version)
             #t))
         (replace 'check
           (lambda* (#:key tests? #:allow-other-keys)
             (when tests?
               (invoke "pytest"))
             #t))
         (add-after 'install 'install-man-page
           (lambda* (#:key outputs #:allow-other-keys)
             (install-file "man/pwclient.1"
                           (string-append
                            (assoc-ref outputs "out")
                            "/share/man/man1"))
             #t)))))
    (native-inputs
     `(("python-pbr" ,python-pbr)
       ("python-pytest" ,python-pytest)
       ("python-pytest-cov" ,python-pytest-cov)
       ("python-mock" ,python-mock)))
    (home-page
     "https://github.com/getpatchwork/pwclient")
    (synopsis "Command-line client for the Patchwork patch tracking tool")
    (description
     "pwclient is a VCS-agnostic tool for interacting with Patchwork, the
web-based patch tracking system.")
    (license gpl2+)))


code:
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014, 2015, 2017, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu packages pciutils)
  #:use-module (guix packages)
  #:use-module (guix download)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (guix utils)
  #:use-module (guix build-system gnu)
  #:use-module (gnu packages)
  #:use-module (gnu packages compression)
  #:use-module (gnu packages pkg-config)
  #:use-module (gnu packages hurd)
  #:use-module (gnu packages linux)
  #:use-module (gnu packages base))

(define-public pciutils
  (package
    (name "pciutils")
    (version "3.7.0")
    (source (origin
              (method url-fetch)
              (uri (string-append
                    "mirror://kernel.org/software/utils/pciutils/pciutils-"
                    version ".tar.xz"))
              (patches (search-patches "pciutils-hurd-configure.patch"))
              (sha256
               (base32
                "1ss0rnfsx8gvqjxaji4mvbhf9xyih4cadmgadbwwv8mnx1xvjh4x"))))
    (build-system gnu-build-system)
    (arguments
     `(#:phases
       (modify-phases %standard-phases
         (replace 'configure
           (lambda* (#:key outputs #:allow-other-keys)
             ;; There's no 'configure' script, just a raw makefile.
             (substitute* "Makefile"
               ,@(if (%current-target-system)
                     `((("^CROSS_COMPILE=.*$")
                        (string-append "CROSS_COMPILE="
                                       ,(%current-target-system) "-"
                                       "\n"))
                       (("^HOST=.*$")
                        (string-append "HOST="
                                       ,(gnu-triplet->nix-system
                                         (%current-target-system)) "\n"))
                       ;; Disable 'install' strip option, that would fail when
                       ;; we are cross-compiling.
                       (("^STRIP=.*$")
                        "STRIP=\n"))
                     '())
               (("^PREFIX=.*$")
                (string-append "PREFIX := " (assoc-ref outputs "out")
                               "\n"))
               (("^MANDIR:=.*$")
                 ;; By default the thing tries to automatically
                 ;; determine whether to use $prefix/man or
                 ;; $prefix/share/man, and wrongly so.
                (string-append "MANDIR := " (assoc-ref outputs "out")
                               "/share/man\n"))

               (("^SHARED=.*$")
                ;; Build libpciutils.so.
                "SHARED := yes\n")
               (("^ZLIB=.*$")
                ;; Ask for zlib support, for 'pci.ids.gz' decompression.
                "ZLIB := yes\n")

               (("^IDSDIR=.*$")
                ;; Installation directory of 'pci.ids.gz'.
                "IDSDIR = $(SHAREDIR)/hwdata\n"))
             #t))
         (replace 'install
           (lambda* (#:key outputs #:allow-other-keys)
             ;; Install the commands, library, and .pc files.
             (invoke "make" "install" "install-lib")))

         ,@(if (hurd-target?)
               '((add-after 'unpack 'apply-hurd-patch
                   (lambda* (#:key inputs #:allow-other-keys)
                     (let ((patch (assoc-ref inputs "hurd-patch")))
                       (invoke "patch" "-p1" "--batch" "-i"
                               patch)))))
               '()))

       ;; Make sure programs have an RPATH so they can find libpciutils.so.
       #:make-flags (list (string-append "LDFLAGS=-Wl,-rpath="
                                         (assoc-ref %outputs "out") "/lib"))

       ;; No test suite.
       #:tests? #f))
    (native-inputs
     `(("which" ,which)
       ("pkg-config" ,pkg-config)))
    (inputs
     `(,@(if (member (or (%current-target-system)
                         (%current-system))
                     (package-supported-systems kmod))
             `(("kmod" ,kmod))
             '())
       ,@(if (hurd-target?)
             `(("hurd-patch" ,(search-patch "pciutils-hurd-fix.patch")))
             '())
       ("zlib" ,zlib)))
    (home-page "https://mj.ucw.cz/sw/pciutils/")
    (synopsis "Programs for inspecting and manipulating PCI devices")
    (description
     "The PCI Utilities are a collection of programs for inspecting and
manipulating configuration of PCI devices, all based on a common portable
library libpci which offers access to the PCI configuration space on a variety
of operating systems.  This includes the @command{lspci} and @command{setpci}
commands.")
    (license license:gpl2+)))