aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--x11-fm/4pane/Makefile23
-rw-r--r--x11-fm/4pane/distinfo3
-rw-r--r--x11-fm/4pane/files/patch-Devices.cpp342
-rw-r--r--x11-fm/4pane/files/patch-Devices.h26
-rw-r--r--x11-fm/4pane/files/patch-Misc.cpp33
-rw-r--r--x11-fm/4pane/files/patch-Mounts.cpp102
-rw-r--r--x11-fm/4pane/pkg-descr6
-rw-r--r--x11-fm/4pane/pkg-plist196
-rw-r--r--x11-fm/Makefile1
9 files changed, 732 insertions, 0 deletions
diff --git a/x11-fm/4pane/Makefile b/x11-fm/4pane/Makefile
new file mode 100644
index 000000000000..78a4ef999717
--- /dev/null
+++ b/x11-fm/4pane/Makefile
@@ -0,0 +1,23 @@
+PORTNAME= 4pane
+PORTVERSION= 7.0
+CATEGORIES= x11-fm
+MASTER_SITES= SF/fourpane/${PORTVERSION}
+
+MAINTAINER= danfe@FreeBSD.org
+COMMENT= Multi-pane, detailed-list graphical file manager
+WWW= http://www.4pane.co.uk/
+
+LICENSE= GPLv3
+
+USES= pkgconfig
+USE_WX= 3.0+
+GNU_CONFIGURE= yes
+CONFIGURE_ARGS= --with-wx-config="${WX_CONFIG}"
+
+OPTIONS_DEFINE= NLS
+OPTIONS_SUB= yes
+
+NLS_USES= gettext
+NLS_CONFIGURE_OFF= --disable-locale
+
+.include <bsd.port.mk>
diff --git a/x11-fm/4pane/distinfo b/x11-fm/4pane/distinfo
new file mode 100644
index 000000000000..9947c9110125
--- /dev/null
+++ b/x11-fm/4pane/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1607257783
+SHA256 (4pane-7.0.tar.gz) = 09716c4000ba193db128d97d04e6bc8c9dfebf11e2755bfc071ce1db339d8b80
+SIZE (4pane-7.0.tar.gz) = 2113199
diff --git a/x11-fm/4pane/files/patch-Devices.cpp b/x11-fm/4pane/files/patch-Devices.cpp
new file mode 100644
index 000000000000..8866393bd213
--- /dev/null
+++ b/x11-fm/4pane/files/patch-Devices.cpp
@@ -0,0 +1,342 @@
+--- Devices.cpp.orig 2020-11-22 11:42:51 UTC
++++ Devices.cpp
+@@ -1357,7 +1357,7 @@ if (!wxFileExists(BLKID))
+ if (wxFileExists(wxT("/usr/bin/blkid"))) BLKID = wxT("/usr/bin/blkid");
+ else
+ { wxArrayString output, errors;long ans;
+- if (wxGetOsDescription().Contains(wxT("kFreeBSD"))) // The kFreeBSD forkpty hangs
++ if (wxGetOsDescription().Contains(wxT("FreeBSD"))) // FreeBSD's forkpty() hangs
+ ans = wxExecute(wxT("which blkid"), output, errors);
+ else
+ ans = ExecuteInPty(wxT("which blkid"), output, errors);
+@@ -1371,7 +1371,7 @@ if (!wxFileExists(LSBLK))
+ if (wxFileExists(wxT("/sbin/lsblk"))) LSBLK = wxT("/sbin/lsblk");
+ else
+ { wxArrayString output, errors; long ans;
+- if (wxGetOsDescription().Contains(wxT("kFreeBSD")))
++ if (wxGetOsDescription().Contains(wxT("FreeBSD")))
+ ans = wxExecute(wxT("which lsblk"), output, errors);
+ else
+ ans = ExecuteInPty(wxT("which lsblk"), output, errors);
+@@ -1590,14 +1590,22 @@ bool DeviceAndMountManager::Checkmtab(wxString& mountp
+ return DeviceAndMountManager::GnuCheckmtab(mountpoint, device);
+ #endif
+
++#ifdef __linux__
+ struct mntent* mnt = NULL;
+
+ FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab
+ if (fmp==NULL) return false;
++#else
++struct statfs* fslist;
+
++int numfs = getmntinfo(&fslist, MNT_NOWAIT);
++if (numfs < 1) return false;
++#endif
++
+ wxString mountpt(mountpoint); FileData mp(mountpt);
+ if (mp.IsSymlink()) mountpt = mp.GetUltimateDestination(); // Cope with a symlink
+
++#ifdef __linux__
+ while (1) // For every mtab entry
+ { mnt = getmntent(fmp); // Get a struct representing a mounted partition
+ if (mnt == NULL)
+@@ -1605,14 +1613,24 @@ while (1)
+
+ wxString mntdir(mnt->mnt_dir, wxConvUTF8);
+ wxString type(mnt->mnt_type, wxConvUTF8); type.MakeLower();
++#else
++for (int i = 0; i < numfs; ++i)
++ { wxString mntdir(fslist[i].f_mntonname, wxConvUTF8);
++ wxString type(fslist[i].f_fstypename, wxConvUTF8); type.MakeLower();
++#endif
+ // Don't try to create a FileData if we're testing a network mount. It's less likely to be symlinked, and e.g. a stale nfs mount hangs lstat!
+ if (!type.StartsWith(wxT("nfs")) && !type.Contains(wxT("sshfs")) && type != wxT("cifs") && type != wxT("smbfs"))
+ { FileData mt(mntdir); if (mt.IsSymlink()) mntdir = mt.GetUltimateDestination(); } // Cope with a symlink
+ if (mntdir == mountpt) // This is the one we're looking for
++#ifdef __linux__
+ { endmntent(fmp);
+ if (device.IsEmpty()) return true; // If we don't care which device is mounted there
+
+ wxString mntfsname(mnt->mnt_fsname, wxConvUTF8); // in case we DO care
++#else
++ { if (device.IsEmpty()) return true;
++ wxString mntfsname(fslist[i].f_mntfromname, wxConvUTF8);
++#endif
+ FileData dev(device); FileData mntfs(mntfsname); // Cope with any symlinks
+ if (dev.IsSymlink()) device = dev.GetUltimateDestination();
+ if (mntfs.IsSymlink()) mntfsname = mntfs.GetUltimateDestination();
+@@ -1649,6 +1667,7 @@ wxString DeviceAndMountManager::WhereIsDeviceMounted(w
+
+ wxString DeviceAndMountManager::WhereIsDeviceMounted(wxString device, size_t type)
+ {
++#ifdef __linux__
+ struct mntent* mnt = NULL;
+
+ FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab
+@@ -1660,6 +1679,17 @@ while (1)
+ wxString mntfsname(mnt->mnt_fsname, wxConvUTF8);
+ if (mntfsname == device)
+ { endmntent(fmp); return wxString(mnt->mnt_dir, wxConvUTF8); } // If it's the one we're looking for, return the associated mountpt
++#else
++struct statfs* fslist;
++
++int numfs = getmntinfo(&fslist, MNT_NOWAIT);
++if (numfs < 1) return wxEmptyString;
++
++for (int i = 0; i < numfs; ++i)
++ { wxString mntfsname(fslist[i].f_mntfromname, wxConvUTF8);
++ if (mntfsname == device)
++ return wxString(fslist[i].f_mntonname, wxConvUTF8);
++#endif
+ }
+
+ // If we're here, the device wasn't found. See if it's actually a symlink for a different device eg /dev/dvd -> /dev/hdc. If so, try that
+@@ -1678,17 +1708,27 @@ return wxEmptyString;
+ }
+
+ //static
++#ifdef __linux__
+ struct mntent* DeviceAndMountManager::ReadMtab(const wxString& partition, bool DvdRamFS /*=false*/) // Is 'partition' currently mounted? Returns struct of data if it is, NULL if it isn't
+ {
+ struct mntent* mnt = NULL;
+
+ FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab
+ if (fmp==NULL) return mnt;
++#else
++struct statfs* DeviceAndMountManager::ReadMtab(const wxString& partition, bool DvdRamFS /*=false*/)
++{
++struct statfs* fslist;
+
++int numfs = getmntinfo(&fslist, MNT_NOWAIT);
++if (numfs < 1) return NULL;
++#endif
++
+ wxString partitionwithsep(partition), partitionwithout(partition); // Avoid the usual '/' issue
+ if (partition.Right(1) == wxFILE_SEP_PATH) partitionwithout = partition.BeforeLast(wxFILE_SEP_PATH);
+ else partitionwithsep << wxFILE_SEP_PATH;
+
++#ifdef __linux__
+ while (1) // For every mtab entry
+ { mnt = getmntent(fmp); // Get a struct representing a mounted partition
+ if (mnt == NULL) break; // If it's null, we've run out of candidates. Return null as flag
+@@ -1706,6 +1746,22 @@ mnt = NULL; return mnt;
+ if (stat.IsSymlink()) { wxString target = stat.GetSymlinkDestination(); return ReadMtab(target, DvdRamFS); }
+
+ mnt = NULL; return mnt; // If we're here, it failed. Return null as flag
++#else
++for (int i = 0; i < numfs; ++i)
++ { wxString mntfsname(fslist[i].f_mntfromname, wxConvUTF8);
++ if (!mntfsname.empty() && ((mntfsname == partitionwithsep) || (mntfsname == partitionwithout)))
++ { if (!DvdRamFS) return &fslist[i];
++ wxString mnttype(fslist[i].f_fstypename, wxConvUTF8);
++ for (size_t n=0; n < RealFilesystemsArray.GetCount(); ++n)
++ if (mnttype.Left(3) == RealFilesystemsArray.Item(n).Left(3)) return &fslist[i];
++ }
++ }
++FileData stat(partition);
++if (stat.IsSymlink())
++ { wxString target = stat.GetSymlinkDestination();
++ return ReadMtab(target, DvdRamFS);
++ } else return NULL;
++#endif
+ }
+
+
+@@ -1887,14 +1943,25 @@ if (!FillPartitionArrayUsingLsblk(true))
+ { pstruct->mountpt = wxString(fs->fs_file, wxConvUTF8); // Store the mountpt
+ pstruct->IsMounted = Checkmtab(pstruct->mountpt, pstruct->device);// & whether it's mounted. Pass the device-name too, so that we only record if the mountpt contains THIS device
+ if (!pstruct->IsMounted) // If it isn't mounted where it's supposed to be, look elsewhere in case it was su-mounted in the 'wrong' place
++#ifdef __linux__
+ { struct mntent* mnt = ReadMtab(pstruct->device);
+ if (mnt != NULL) { pstruct->mountpt = wxString(mnt->mnt_dir, wxConvUTF8); pstruct->IsMounted = true; }
++#else
++ { struct statfs* mnt = ReadMtab(pstruct->device);
++ if (mnt != NULL) { pstruct->mountpt = wxString(mnt->f_mntonname, wxConvUTF8); pstruct->IsMounted = true; }
++#endif
+ }
+ }
+ else // If we didn't find it in fstab, check mtab anyway, in case someone mounted it the hard way
++#ifdef __linux__
+ { struct mntent* mnt = ReadMtab(pstruct->device);
+ if (mnt != NULL)
+ { pstruct->mountpt = wxString(mnt->mnt_dir, wxConvUTF8); // Store the mountpt
++#else
++ { struct statfs* mnt = ReadMtab(pstruct->device);
++ if (mnt != NULL)
++ { pstruct->mountpt = wxString(mnt->f_mntonname, wxConvUTF8);
++#endif
+ pstruct->IsMounted = true; // It's mounted by definition: it's in mtab
+ }
+ else pstruct->IsMounted = false; // Otherwise reset this bool, as it's otherwise undefined
+@@ -2027,6 +2094,7 @@ void DeviceAndMountManager::FindMountedImages() // Ad
+
+ void DeviceAndMountManager::FindMountedImages() // Add mounted iso-images from mtab to array
+ {
++#ifdef __linux__
+ FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab
+ if (fmp==NULL) return;
+
+@@ -2036,12 +2104,26 @@ while (1)
+ { endmntent(fmp); return; } // If it's null, we've finished mtab
+
+ wxString device(mnt->mnt_fsname, wxConvUTF8); // Make the 'device' into a wxString for convenience
++#else
++struct statfs* fslist;
++
++int numfs = getmntinfo(&fslist, MNT_NOWAIT);
++if (numfs < 1) return;
++
++for (int i = 0; i < numfs; ++i)
++ { wxString device(fslist[i].f_mntfromname, wxConvUTF8);
++#endif
+ // If it starts with a '/dev/loop' or with a '/' but not with /dev/ or // it's probably an iso-image
+ if ((device.Left(9) == wxT("/dev/loop")) || (device.GetChar(0) == wxT('/') &&
+ !(device.Left(5) == wxT("/dev/") || device.Left(2) == wxT("//"))))
+ { struct PartitionStruct* newmnt = new struct PartitionStruct; // store in structarray
++#ifdef __linux__
+ newmnt->device = wxString(mnt->mnt_fsname, wxConvUTF8);
+ newmnt->mountpt = wxString(mnt->mnt_dir, wxConvUTF8);
++#else
++ newmnt->device = wxString(fslist[i].f_mntfromname, wxConvUTF8);
++ newmnt->mountpt = wxString(fslist[i].f_mntonname, wxConvUTF8);
++#endif
+ newmnt->IsMounted = true; // By definition
+ PartitionArray->Add(newmnt);
+ }
+@@ -2153,6 +2235,7 @@ for (size_t n=0; n < partitions.GetCount(); ++n)
+ for (size_t n=0; n < partitions.GetCount(); ++n)
+ { wxString item = partitions.Item(n);
+ if (item == dev || item == symtarget)
++#ifdef __linux__
+ { struct mntent* mnt = NULL; // Found an entry. Look for it in mtab
+ FILE* fmp = setmntent (_PATH_MOUNTED, "r"); if (fmp==NULL) { endfsent(); return answerarray.GetCount() > 0; }
+ while (1)
+@@ -2166,6 +2249,16 @@ for (size_t n=0; n < partitions.GetCount(); ++n)
+ if (wxString(mnt->mnt_dir,wxConvUTF8) == mountpts.Item(n)) // but it's already mounted here
+ { endmntent(fmp); break; } // so look in 'partitions' array for another entry
+ }
++#else
++ { struct statfs* fslist;
++ int numfs = getmntinfo(&fslist, MNT_NOWAIT);
++ if (numfs < 1) return answerarray.GetCount() > 0;
++ for (int i = 0; i < numfs; ++i)
++ if (wxString(fslist[i].f_mntfromname, wxConvUTF8) == dev || wxString(fslist[i].f_mntfromname, wxConvUTF8) == symtarget)
++ if (wxString(fslist[i].f_mntonname, wxConvUTF8) == mountpts.Item(n)) goto another;
++ answerarray.Add(mountpts.Item(n));
++another:;
++#endif
+ }
+ }
+
+@@ -2921,8 +3014,13 @@ for (size_t n=0; n < allpartitions.GetCount(); ++n)
+ { if (allpartitions[n].Left(len) == dev.Left(len)) // If the 1st 'len' letters of the NAME bit of this partition match dev ie /dev/sda1 matches /dev/sda
+ { partitions.Add(allpartitions[n]); // store it in the real partition array
+
++#ifdef __linux__
+ struct mntent* mnt = ReadMtab(allpartitions[n]); // Now see if this partition is currently mounted
+ if (mnt != NULL) mountpts.Add(wxString(mnt->mnt_dir, wxConvUTF8)); // If so, store the mountpt
++#else
++ struct statfs* mnt = ReadMtab(allpartitions[n]);
++ if (mnt != NULL) mountpts.Add(wxString(mnt->f_mntonname, wxConvUTF8));
++#endif
+ else mountpts.Add(wxEmptyString); // Otherwise store ""
+ }
+ }
+@@ -2944,7 +3042,11 @@ wxTextFile file; //
+ void DeviceAndMountManager::CheckSupermountTab(wxArrayString& partitions, wxArrayString& mountpts, wxString dev, bool SearchMtab) // In Supermount systems, finds data for this device
+ {
+ wxTextFile file; // Create a textfile
++#ifdef __linux__
+ if (SearchMtab) file.Create(wxT(_PATH_MOUNTED)); // using mtab
++#else
++if (SearchMtab) return;
++#endif
+ else file.Create(wxT(_PATH_FSTAB)); // or fstab
+ if (!file.Exists()) return;
+ file.Open(); if (!file.IsOpened()) return;
+@@ -2971,17 +3073,27 @@ void DeviceAndMountManager::SearchMtab(wxArrayString&
+
+ void DeviceAndMountManager::SearchMtab(wxArrayString& partitions, wxArrayString& mountpts, wxString dev /*=wxEmptyString*/) // Loads arrays with data for the named device, or for all devices. NB Only finds mounted partitions
+ {
++#ifdef __linux__
+ struct mntent* mnt = NULL;
++#else
++struct statfs* fslist;
++#endif
+
+ partitions.Empty(); mountpts.Empty(); // Empty the arrays of any old data: we don't want to append!
+
++#ifdef __linux__
+ FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab
+ if (fmp==NULL) return;
++#else
++int numfs = getmntinfo(&fslist, MNT_NOWAIT);
++if (numfs < 1) return;
++#endif
+
+ wxString mask;
+ if (dev.IsEmpty()) mask = AUTOMOUNT_USB_PREFIX; // We normally search for all AUTOMOUNT_USB_PREFIX devices, probably "/dev/sd"
+ else mask = dev; // but if dev isn't empty, use this instead
+
++#ifdef __linux__
+ while (1) // For every mtab entry
+ { mnt = getmntent(fmp); // Get a struct representing a mounted partition
+ if (mnt == NULL) { endmntent(fmp); return; } // If it's null, we've run out of candidates
+@@ -2990,18 +3102,29 @@ while (1) //
+ if (wxString(mnt->mnt_fsname, wxConvUTF8).Left(mask.Len()) == mask)
+ { partitions.Add(wxString(mnt->mnt_fsname, wxConvUTF8)); // If so, store the devnode and mountpt
+ mountpts.Add(wxString(mnt->mnt_dir, wxConvUTF8));
++#else
++for (int i = 0; i < numfs; ++i)
++ { if (wxString(fslist[i].f_mntfromname, wxConvUTF8).Left(mask.Len()) == mask)
++ { partitions.Add(wxString(fslist[i].f_mntfromname, wxConvUTF8));
++ mountpts.Add(wxString(fslist[i].f_mntonname, wxConvUTF8));
++#endif
+ }
+ }
+ }
+
+ void DeviceAndMountManager::SearchMtabForStandardMounts(wxString& device, wxArrayString& mountpts) // Finds ext2 etc mountpts for the device ie not subfs. Used for DVD-RAM
+ {
++#ifdef __linux__
+ struct mntent* mnt = NULL;
++#else
++struct statfs* fslist;
++#endif
+ mountpts.Empty(); // Empty the array of any old data: we don't want to append!
+
+ wxString symtarget; FileData fd(device); // Beware of the symlink
+ if (fd.IsSymlink()) symtarget = fd.GetUltimateDestination();
+
++#ifdef __linux__
+ FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab
+ if (fmp==NULL) return;
+
+@@ -3012,12 +3135,26 @@ while (1) //
+ bool found = false;
+ if (wxString(mnt->mnt_fsname, wxConvUTF8).Left(device.Len()) == device) found=true; // See if this is a mount for the device we're interested in
+ else if (!symtarget.IsEmpty() && wxString(mnt->mnt_fsname, wxConvUTF8).Left(symtarget.Len()) == symtarget) found=true; // Try again with any symlink target
++#else
++int numfs = getmntinfo(&fslist, MNT_NOWAIT);
++if (numfs < 1) return;
+
++for (int i = 0; i < numfs; ++i)
++ { bool found = false;
++ if (wxString(fslist[i].f_mntfromname, wxConvUTF8).Left(device.Len()) == device) found=true;
++ else if (!symtarget.IsEmpty() && wxString(fslist[i].f_mntfromname, wxConvUTF8).Left(symtarget.Len()) == symtarget) found=true;
++#endif
++
+ if (!found) continue; // Wrong device
+
+ for (size_t n=0; n < RealFilesystemsArray.GetCount(); ++n) // For DVD-RAM, we're only interested in filesystems like ext2 not eg subfs
++#ifdef __linux__
+ if (wxString(mnt->mnt_type, wxConvUTF8).Left(3) == RealFilesystemsArray.Item(n).Left(3))
+ { mountpts.Add(wxString(mnt->mnt_dir, wxConvUTF8)); break; } // If the type is right, this mountpt is one we want to store
++#else
++ if (wxString(fslist[i].f_fstypename, wxConvUTF8).Left(3) == RealFilesystemsArray.Item(n).Left(3))
++ { mountpts.Add(wxString(fslist[i].f_mntonname, wxConvUTF8)); break; }
++#endif
+ }
+ }
+
diff --git a/x11-fm/4pane/files/patch-Devices.h b/x11-fm/4pane/files/patch-Devices.h
new file mode 100644
index 000000000000..12ffcf07852a
--- /dev/null
+++ b/x11-fm/4pane/files/patch-Devices.h
@@ -0,0 +1,26 @@
+--- Devices.h.orig 2020-11-22 11:43:42 UTC
++++ Devices.h
+@@ -13,7 +13,11 @@
+ #include "wx/config.h"
+
+ #include <fstab.h>
++#ifdef __linux__
+ #include <mntent.h>
++#else
++#include <sys/mount.h>
++#endif
+
+ #include "Externs.h"
+
+@@ -310,7 +314,11 @@ void OnUnMountNetwork();
+ void OnMountSshfs();
+ void OnMountSamba();
+ void OnUnMountNetwork();
++#ifdef __linux__
+ static struct mntent* ReadMtab(const wxString& partition, bool DvdRamFS=false); // Goes thru mtab, to find if 'partition' currently mounted. If DvdRamFS, ignores eg subfs mounts (used for DVD-RAM)
++#else
++static struct statfs* ReadMtab(const wxString& partition, bool DvdRamFS=false);
++#endif
+ static struct fstab* ReadFstab(const wxString& dev, const wxString& uuid = "", const wxString& label = ""); // Search fstab for a line for this device
+ static struct fstab* ReadFstab(const PartitionStruct* ps) { return ReadFstab(ps->device, ps->uuid, ps->label); }
+ static bool FindUnmountedFstabEntry(wxString& dev, wxArrayString& answerarray); // Ditto but only returning Unmounted entries. Used for DVD-RAM
diff --git a/x11-fm/4pane/files/patch-Misc.cpp b/x11-fm/4pane/files/patch-Misc.cpp
new file mode 100644
index 000000000000..fc3e96fbcf6f
--- /dev/null
+++ b/x11-fm/4pane/files/patch-Misc.cpp
@@ -0,0 +1,33 @@
+--- Misc.cpp.orig 2020-11-19 18:24:13 UTC
++++ Misc.cpp
+@@ -511,7 +511,7 @@ wxArrayString output, errors;
+ wxCHECK_MSG(!lib.empty(), "", "Empty parameter");
+
+ wxArrayString output, errors;
+-long ans = wxExecute("sh -c \"/sbin/ldconfig -p | grep " + lib + '\"', output,errors);
++long ans = wxExecute("sh -c \"/sbin/ldconfig -r | grep " + lib + '\"', output,errors);
+ if (ans != 0 || output.IsEmpty()) return "";
+
+ wxString fpath = output.Item(0).AfterLast(' ');
+@@ -666,7 +666,12 @@ if (clientDC) delete clientDC;
+ #endif
+ //-----------------------------------------------------------------------------------------------------------------------
+
++#ifdef __linux__
+ #include <pty.h>
++#else
++#include <termios.h>
++#include <libutil.h>
++#endif
+ #include <errno.h>
+ #include <sys/wait.h>
+
+@@ -779,7 +784,7 @@ if (cmd.empty()) return ERROR_RETURN_CODE;
+ {
+ if (cmd.empty()) return ERROR_RETURN_CODE;
+
+-if (wxGetOsDescription().Contains(wxT("kFreeBSD"))) // The kFreeBSD forkpty hangs
++if (wxGetOsDescription().Contains(wxT("FreeBSD"))) // FreeBSD's forkpty() hangs
+ { if (GetCallerTextCtrl())
+ InformCallerOnTerminate();
+ return ERROR_RETURN_CODE;
diff --git a/x11-fm/4pane/files/patch-Mounts.cpp b/x11-fm/4pane/files/patch-Mounts.cpp
new file mode 100644
index 000000000000..b0f4b6d28554
--- /dev/null
+++ b/x11-fm/4pane/files/patch-Mounts.cpp
@@ -0,0 +1,102 @@
+--- Mounts.cpp.orig 2020-11-22 11:42:50 UTC
++++ Mounts.cpp
+@@ -866,8 +866,13 @@ for (size_t n=0; n < parent->PartitionArray->GetCount(
+ if (parent->PartitionArray->Item(n)->device == dev.BeforeFirst(' ')) // BeforeFirst in case of "/dev/sda1 $UUID/$LABEL"
+ { if (GetDataFromMtab) // If we're unmounting, we can't rely on the PartitionArray info: the partition may not have been mounted where fstab intended
+ { FstabMountptTxt->Clear();
++#ifdef __linux__
+ struct mntent* mnt = parent->ReadMtab(dev.BeforeFirst(' ')); // So see where it really is
+ if (mnt != NULL) FstabMountptTxt->ChangeValue(wxString(mnt->mnt_dir, wxConvUTF8));
++#else
++ struct statfs* mnt = parent->ReadMtab(dev.BeforeFirst(' '));
++ if (mnt != NULL) FstabMountptTxt->ChangeValue(wxString(mnt->f_mntonname, wxConvUTF8));
++#endif
+ return;
+ }
+ else
+@@ -968,10 +973,18 @@ FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8)
+ InFstab = (fs != NULL); // Store or null the data according to the result
+ FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8) : wxT(""));
+
++#ifdef __linux__
+ struct mntent* mnt = DeviceAndMountManager::ReadMtab(Image); // Now read mtab to see if the share's already mounted
++#else
++struct statfs* mnt = DeviceAndMountManager::ReadMtab(Image);
++#endif
+ IsMounted = (mnt != NULL);
+ AlreadyMounted->Show(IsMounted); GetSizer()->Layout(); // If it is mounted, expose the wxStaticTxt that says so (and Layout, else 2.8.0 displays it in top left corner!)
++#ifdef __linux__
+ AtMountPt = (IsMounted ? wxString(mnt->mnt_dir, wxConvUTF8) : wxT("")); // Store any mountpt, or delete any previous entry
++#else
++AtMountPt = (IsMounted ? wxString(mnt->f_mntonname, wxConvUTF8) : wxT(""));
++#endif
+ if (IsMounted)
+ MountptCombo->SetValue(AtMountPt); // Put any mountpt in the combobox
+ else if (InFstab)
+@@ -1209,11 +1222,19 @@ FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8)
+ InFstab = (fs != NULL); // Store or null the data according to the result
+ FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8) : wxT(""));
+
++#ifdef __linux__
+ struct mntent* mnt = DeviceAndMountManager::ReadMtab(device1); // Now read mtab to see if the share's already mounted
++#else
++struct statfs* mnt = DeviceAndMountManager::ReadMtab(device1);
++#endif
+ if (mnt == NULL) mnt = DeviceAndMountManager::ReadMtab(device2); // Null means not found, so try again with the IP version
+ IsMounted = (mnt != NULL);
+ AlreadyMounted->Show(IsMounted); GetSizer()->Layout(); // If it is mounted, expose the wxStaticTxt that says so (and Layout, else 2.8.0 displays it in top left corner!)
++#ifdef __linux__
+ AtMountPt = (IsMounted ? wxString(mnt->mnt_dir, wxConvUTF8) : wxT("")); // Store any mountpt, or delete any previous entry
++#else
++AtMountPt = (IsMounted ? wxString(mnt->f_mntonname, wxConvUTF8) : wxT(""));
++#endif
+ if (IsMounted)
+ MountptCombo->SetValue(AtMountPt);
+ else if (InFstab)
+@@ -1503,10 +1524,18 @@ FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8)
+ InFstab = (fs != NULL); // Store or null the data according to the result
+ FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8) : wxT(""));
+
++#ifdef __linux__
+ mntent* mnt = DeviceAndMountManager::ReadMtab(device); // Now read mtab to see if the share's already mounted
++#else
++struct statfs* mnt = DeviceAndMountManager::ReadMtab(device);
++#endif
+ IsMounted = (mnt != NULL);
+ AlreadyMounted->Show(IsMounted); GetSizer()->Layout(); // If it is mounted, expose the wxStaticTxt that says so (and Layout, else 2.8.0 displays it in top left corner!)
++#ifdef __linux__
+ AtMountPt = (IsMounted ? wxString(mnt->mnt_dir, wxConvUTF8) : wxT("")); // Store any mountpt, or delete any previous entry
++#else
++AtMountPt = (IsMounted ? wxString(mnt->f_mntonname, wxConvUTF8) : wxT(""));
++#endif
+
+ if (IsMounted)
+ MountptCombo->SetValue(AtMountPt);
+@@ -1736,6 +1765,7 @@ void UnMountSambaDialog::SearchForNetworkMounts() //
+
+ void UnMountSambaDialog::SearchForNetworkMounts() // Scans mtab for established NFS & samba mounts
+ {
++#ifdef __linux__
+ FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab
+ if (fmp==NULL) return;
+
+@@ -1749,6 +1779,19 @@ while (1)
+ { struct PartitionStruct* newmnt = new struct PartitionStruct;
+ newmnt->device = wxString(mnt->mnt_fsname, wxConvUTF8);
+ newmnt->mountpt = wxString(mnt->mnt_dir, wxConvUTF8);
++#else
++struct statfs *fslist;
++
++int numfs = getmntinfo(&fslist, MNT_NOWAIT);
++if (numfs < 1) return;
++
++for (int i = 0; i < numfs; ++i)
++ { wxString type(fslist[i].f_fstypename, wxConvUTF8);
++ if (ParseNetworkFstype(type) != MT_invalid)
++ { struct PartitionStruct* newmnt = new struct PartitionStruct;
++ newmnt->device = wxString(fslist[i].f_mntfromname, wxConvUTF8);
++ newmnt->mountpt = wxString(fslist[i].f_mntonname, wxConvUTF8);
++#endif
+ newmnt->type = type;
+ Mntarray.Add(newmnt);
+ }
diff --git a/x11-fm/4pane/pkg-descr b/x11-fm/4pane/pkg-descr
new file mode 100644
index 000000000000..efd1c0290336
--- /dev/null
+++ b/x11-fm/4pane/pkg-descr
@@ -0,0 +1,6 @@
+4Pane is a multi-pane, detailed-list file manager for Unix-like systems.
+It is designed to be fully-featured without bloat, and aims for speed
+rather than visual effects. In addition to standard file manager things,
+it offers multiple undo and redo of most operations (including deletions),
+archive management including "virtual browsing" inside archives, multiple
+renaming/duplication of files, terminal emulator, and user-defined tools.
diff --git a/x11-fm/4pane/pkg-plist b/x11-fm/4pane/pkg-plist
new file mode 100644
index 000000000000..a8a141a5d3ac
--- /dev/null
+++ b/x11-fm/4pane/pkg-plist
@@ -0,0 +1,196 @@
+bin/4Pane
+bin/4pane
+share/4Pane/bitmaps/4Pane.png
+share/4Pane/bitmaps/4PaneIcon16.xpm
+share/4Pane/bitmaps/4PaneIcon32.xpm
+share/4Pane/bitmaps/4PaneIcon40x32.xpm
+share/4Pane/bitmaps/4PaneIcon48.png
+share/4Pane/bitmaps/4PaneIcon48.xpm
+share/4Pane/bitmaps/DelTab.png
+share/4Pane/bitmaps/DnDSelectedCursor.png
+share/4Pane/bitmaps/DnDStdCursor.png
+share/4Pane/bitmaps/MyDocuments.xpm
+share/4Pane/bitmaps/NewTab.png
+share/4Pane/bitmaps/Preview.png
+share/4Pane/bitmaps/UsbMem.xpm
+share/4Pane/bitmaps/UsbMulticard.xpm
+share/4Pane/bitmaps/UsbPen.xpm
+share/4Pane/bitmaps/abiword.png
+share/4Pane/bitmaps/back.xpm
+share/4Pane/bitmaps/bm1_button.xpm
+share/4Pane/bitmaps/bm2_button.xpm
+share/4Pane/bitmaps/bm3_button.xpm
+share/4Pane/bitmaps/cdda.png
+share/4Pane/bitmaps/cdr.xpm
+share/4Pane/bitmaps/cdrom.xpm
+share/4Pane/bitmaps/chrome-chromium.png
+share/4Pane/bitmaps/clear_right.xpm
+share/4Pane/bitmaps/connect_no.xpm
+share/4Pane/bitmaps/dir_up.xpm
+share/4Pane/bitmaps/down.xpm
+share/4Pane/bitmaps/dragicon.png
+share/4Pane/bitmaps/evince.xpm
+share/4Pane/bitmaps/featherpad.png
+share/4Pane/bitmaps/fileopen.xpm
+share/4Pane/bitmaps/firefox.png
+share/4Pane/bitmaps/floppy.xpm
+share/4Pane/bitmaps/forward.xpm
+share/4Pane/bitmaps/gedit.xpm
+share/4Pane/bitmaps/gjots.png
+share/4Pane/bitmaps/gohome.xpm
+share/4Pane/bitmaps/gphoto2.png
+share/4Pane/bitmaps/harddisk-usb.xpm
+share/4Pane/bitmaps/harddisk.xpm
+share/4Pane/bitmaps/hardlink.png
+share/4Pane/bitmaps/help.png
+share/4Pane/bitmaps/iceweasel.png
+share/4Pane/bitmaps/kedit.xpm
+share/4Pane/bitmaps/kwrite.xpm
+share/4Pane/bitmaps/largedropdown.png
+share/4Pane/bitmaps/largedropdown.xpm
+share/4Pane/bitmaps/libreoffice.png
+share/4Pane/bitmaps/mate-text-editor.png
+share/4Pane/bitmaps/mousepad.png
+share/4Pane/bitmaps/mozillacrystal.png
+share/4Pane/bitmaps/mtp.png
+share/4Pane/bitmaps/new_dir.xpm
+share/4Pane/bitmaps/openoffice.png
+share/4Pane/bitmaps/palemoon.png
+share/4Pane/bitmaps/photocopier_0.png
+share/4Pane/bitmaps/photocopier_1.png
+share/4Pane/bitmaps/photocopier_10.png
+share/4Pane/bitmaps/photocopier_11.png
+share/4Pane/bitmaps/photocopier_12.png
+share/4Pane/bitmaps/photocopier_13.png
+share/4Pane/bitmaps/photocopier_14.png
+share/4Pane/bitmaps/photocopier_15.png
+share/4Pane/bitmaps/photocopier_16.png
+share/4Pane/bitmaps/photocopier_17.png
+share/4Pane/bitmaps/photocopier_18.png
+share/4Pane/bitmaps/photocopier_19.png
+share/4Pane/bitmaps/photocopier_2.png
+share/4Pane/bitmaps/photocopier_20.png
+share/4Pane/bitmaps/photocopier_21.png
+share/4Pane/bitmaps/photocopier_22.png
+share/4Pane/bitmaps/photocopier_23.png
+share/4Pane/bitmaps/photocopier_24.png
+share/4Pane/bitmaps/photocopier_25.png
+share/4Pane/bitmaps/photocopier_26.png
+share/4Pane/bitmaps/photocopier_27.png
+share/4Pane/bitmaps/photocopier_28.png
+share/4Pane/bitmaps/photocopier_29.png
+share/4Pane/bitmaps/photocopier_3.png
+share/4Pane/bitmaps/photocopier_30.png
+share/4Pane/bitmaps/photocopier_31.png
+share/4Pane/bitmaps/photocopier_32.png
+share/4Pane/bitmaps/photocopier_33.png
+share/4Pane/bitmaps/photocopier_34.png
+share/4Pane/bitmaps/photocopier_35.png
+share/4Pane/bitmaps/photocopier_36.png
+share/4Pane/bitmaps/photocopier_37.png
+share/4Pane/bitmaps/photocopier_38.png
+share/4Pane/bitmaps/photocopier_39.png
+share/4Pane/bitmaps/photocopier_4.png
+share/4Pane/bitmaps/photocopier_40.png
+share/4Pane/bitmaps/photocopier_41.png
+share/4Pane/bitmaps/photocopier_42.png
+share/4Pane/bitmaps/photocopier_43.png
+share/4Pane/bitmaps/photocopier_5.png
+share/4Pane/bitmaps/photocopier_6.png
+share/4Pane/bitmaps/photocopier_7.png
+share/4Pane/bitmaps/photocopier_8.png
+share/4Pane/bitmaps/photocopier_9.png
+share/4Pane/bitmaps/seamonkey.png
+share/4Pane/bitmaps/smalldropdown.png
+share/4Pane/bitmaps/smalldropdown.xpm
+share/4Pane/bitmaps/softlink.png
+share/4Pane/bitmaps/toparent.xpm
+share/4Pane/bitmaps/unknown.xpm
+share/4Pane/rc/4Pane.desktop
+share/4Pane/rc/configuredialogs.xrc
+share/4Pane/rc/dialogs.xrc
+share/4Pane/rc/moredialogs.xrc
+share/doc/4Pane/About.htm
+share/doc/4Pane/Archive.htm
+share/doc/4Pane/ArchiveBrowse.htm
+share/doc/4Pane/Bookmarks.htm
+share/doc/4Pane/Chapt.con
+share/doc/4Pane/Chapt.hhc
+share/doc/4Pane/Chapt.hhk
+share/doc/4Pane/Chapt.hhp
+share/doc/4Pane/Configure.htm
+share/doc/4Pane/ConfigureUserDefTools.htm
+share/doc/4Pane/ConfiguringDevices.htm
+share/doc/4Pane/ConfiguringDisplay.htm
+share/doc/4Pane/ConfiguringMisc.htm
+share/doc/4Pane/ConfiguringNetworks.htm
+share/doc/4Pane/ConfiguringShortcuts.htm
+share/doc/4Pane/ConfiguringTerminals.htm
+share/doc/4Pane/Contents.htm
+share/doc/4Pane/ContextMenu.htm
+share/doc/4Pane/Copier.png
+share/doc/4Pane/Devices.htm
+share/doc/4Pane/Display.htm
+share/doc/4Pane/DnD.htm
+share/doc/4Pane/DnDSelectedCursor.png
+share/doc/4Pane/DnDStdCursor.png
+share/doc/4Pane/Edit.htm
+share/doc/4Pane/Editors.htm
+share/doc/4Pane/Export.htm
+share/doc/4Pane/FAQ.htm
+share/doc/4Pane/Features.htm
+share/doc/4Pane/FileviewCols.htm
+share/doc/4Pane/Filter.htm
+share/doc/4Pane/Hardlink.png
+share/doc/4Pane/Introduction.htm
+share/doc/4Pane/KeyboardNavigation.htm
+share/doc/4Pane/Licence.htm
+share/doc/4Pane/Menu.htm
+share/doc/4Pane/Mount.htm
+share/doc/4Pane/Move.png
+share/doc/4Pane/MultipleRenDup.htm
+share/doc/4Pane/Open.htm
+share/doc/4Pane/OpenWith.htm
+share/doc/4Pane/Options.htm
+share/doc/4Pane/Previews.htm
+share/doc/4Pane/Properties.htm
+share/doc/4Pane/Quickstart.htm
+share/doc/4Pane/RAQ.htm
+share/doc/4Pane/RegExpHelp.htm
+share/doc/4Pane/Running.htm
+share/doc/4Pane/Softlink.png
+share/doc/4Pane/Statusbar.htm
+share/doc/4Pane/Tabs.htm
+share/doc/4Pane/TerminalEm.htm
+share/doc/4Pane/Toolbar.htm
+share/doc/4Pane/Tools.htm
+share/doc/4Pane/UnRedo.htm
+share/doc/4Pane/Using4Pane.htm
+share/doc/4Pane/View.htm
+share/doc/4Pane/back.gif
+share/doc/4Pane/forward.gif
+share/doc/4Pane/up.gif
+share/icons/hicolor/48x48/apps/4Pane.png
+share/icons/hicolor/scalable/apps/4Pane.svg
+%%NLS%%share/locale/ar/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/ca/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/da/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/de/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/el/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/es/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/et/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/fa/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/fi_FI/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/fr/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/fr_FR/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/it/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/ja/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/nl/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/pl/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/pt_BR/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/ru/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/tr/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/uk_UA/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/vi/LC_MESSAGES/4Pane.mo
+%%NLS%%share/locale/zh_CN/LC_MESSAGES/4Pane.mo
+share/metainfo/4Pane.appdata.xml
diff --git a/x11-fm/Makefile b/x11-fm/Makefile
index d83874fd104e..2520a9d95326 100644
--- a/x11-fm/Makefile
+++ b/x11-fm/Makefile
@@ -1,5 +1,6 @@
COMMENT = X11 file managers
+ SUBDIR += 4pane
SUBDIR += arqiver
SUBDIR += caja
SUBDIR += catseye-fm