2013-02-14 23:29:28 +00:00
|
|
|
|
This patch adds bindings to Linux syscalls for which glibc has symbols.
|
|
|
|
|
|
2013-02-15 23:29:43 +00:00
|
|
|
|
Using the FFI would have been nice, but that's not an option when using
|
|
|
|
|
a statically-linked Guile in an initrd that doesn't have libc.so around.
|
|
|
|
|
|
2013-02-14 23:29:28 +00:00
|
|
|
|
diff --git a/libguile/posix.c b/libguile/posix.c
|
2013-02-15 23:29:43 +00:00
|
|
|
|
index 324f21b..cbee94d 100644
|
2013-02-14 23:29:28 +00:00
|
|
|
|
--- a/libguile/posix.c
|
|
|
|
|
+++ b/libguile/posix.c
|
2015-05-23 19:10:34 +00:00
|
|
|
|
@@ -2245,6 +2245,263 @@ scm_init_popen (void)
|
2013-02-14 23:29:28 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+/* Linux! */
|
2015-05-23 19:10:34 +00:00
|
|
|
|
+#ifdef __linux__
|
2013-02-14 23:29:28 +00:00
|
|
|
|
+
|
|
|
|
|
+#include <sys/mount.h>
|
|
|
|
|
+#include "libguile/foreign.h"
|
|
|
|
|
+#include "libguile/bytevectors.h"
|
|
|
|
|
+
|
|
|
|
|
+SCM_DEFINE (scm_mount, "mount", 3, 2, 0,
|
|
|
|
|
+ (SCM source, SCM target, SCM type, SCM flags, SCM data),
|
|
|
|
|
+ "Mount file system of @var{type} specified by @var{source} "
|
|
|
|
|
+ "on @var{target}.")
|
|
|
|
|
+#define FUNC_NAME s_scm_mount
|
|
|
|
|
+{
|
|
|
|
|
+ int err;
|
|
|
|
|
+ char *c_source, *c_target, *c_type;
|
|
|
|
|
+ unsigned long c_flags;
|
|
|
|
|
+ void *c_data;
|
|
|
|
|
+
|
|
|
|
|
+ c_source = scm_to_locale_string (source);
|
|
|
|
|
+ c_target = scm_to_locale_string (target);
|
|
|
|
|
+ c_type = scm_to_locale_string (type);
|
|
|
|
|
+ c_flags = SCM_UNBNDP (flags) ? 0 : scm_to_ulong (flags);
|
|
|
|
|
+ c_data = SCM_UNBNDP (data) ? NULL : scm_to_pointer (data);
|
|
|
|
|
+
|
|
|
|
|
+ err = mount (c_source, c_target, c_type, c_flags, c_data);
|
|
|
|
|
+ if (err != 0)
|
|
|
|
|
+ err = errno;
|
|
|
|
|
+
|
|
|
|
|
+ free (c_source);
|
|
|
|
|
+ free (c_target);
|
|
|
|
|
+ free (c_type);
|
|
|
|
|
+
|
|
|
|
|
+ if (err != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ errno = err;
|
|
|
|
|
+ SCM_SYSERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return SCM_UNSPECIFIED;
|
|
|
|
|
+}
|
|
|
|
|
+#undef FUNC_NAME
|
|
|
|
|
+
|
|
|
|
|
+/* Linux's module installation syscall. See `kernel/module.c' in Linux;
|
|
|
|
|
+ the function itself is part of the GNU libc.
|
|
|
|
|
+
|
|
|
|
|
+ Load the LEN bytes at MODULE as a kernel module, with arguments from
|
|
|
|
|
+ ARGS, a space-separated list of options. */
|
|
|
|
|
+extern long init_module (void *module, unsigned long len, const char *args);
|
|
|
|
|
+
|
|
|
|
|
+SCM_DEFINE (scm_load_linux_module, "load-linux-module", 1, 1, 0,
|
|
|
|
|
+ (SCM data, SCM options),
|
|
|
|
|
+ "Load the Linux kernel module whose contents are in bytevector "
|
|
|
|
|
+ "DATA (the contents of a @code{.ko} file), with the arguments "
|
|
|
|
|
+ "from the OPTIONS string.")
|
|
|
|
|
+#define FUNC_NAME s_scm_load_linux_module
|
|
|
|
|
+{
|
|
|
|
|
+ long err;
|
|
|
|
|
+ void *c_data;
|
|
|
|
|
+ unsigned long c_len;
|
|
|
|
|
+ char *c_options;
|
|
|
|
|
+
|
|
|
|
|
+ SCM_VALIDATE_BYTEVECTOR (SCM_ARG1, data);
|
|
|
|
|
+
|
|
|
|
|
+ c_data = SCM_BYTEVECTOR_CONTENTS (data);
|
|
|
|
|
+ c_len = SCM_BYTEVECTOR_LENGTH (data);
|
|
|
|
|
+ c_options =
|
|
|
|
|
+ scm_to_locale_string (SCM_UNBNDP (options) ? scm_nullstr : options);
|
|
|
|
|
+
|
|
|
|
|
+ err = init_module (c_data, c_len, c_options);
|
|
|
|
|
+
|
|
|
|
|
+ free (c_options);
|
|
|
|
|
+
|
|
|
|
|
+ if (err != 0)
|
2014-11-28 14:08:56 +00:00
|
|
|
|
+ SCM_SYSERROR;
|
2013-02-14 23:29:28 +00:00
|
|
|
|
+
|
|
|
|
|
+ return SCM_UNSPECIFIED;
|
|
|
|
|
+}
|
|
|
|
|
+#undef FUNC_NAME
|
|
|
|
|
+
|
2013-02-15 23:29:43 +00:00
|
|
|
|
+/* Rebooting, halting, and all that. */
|
|
|
|
|
+
|
|
|
|
|
+#include <sys/reboot.h>
|
|
|
|
|
+
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_RB_AUTOBOOT, "RB_AUTOBOOT",
|
|
|
|
|
+ scm_from_int (RB_AUTOBOOT));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_RB_HALT_SYSTEM, "RB_HALT_SYSTEM",
|
|
|
|
|
+ scm_from_int (RB_HALT_SYSTEM));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_RB_ENABLE_CAD, "RB_ENABLE_CAD",
|
|
|
|
|
+ scm_from_int (RB_ENABLE_CAD));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_RB_DISABLE_CAD, "RB_DISABLE_CAD",
|
|
|
|
|
+ scm_from_int (RB_DISABLE_CAD));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_RB_POWER_OFF, "RB_POWER_OFF",
|
|
|
|
|
+ scm_from_int (RB_POWER_OFF));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_RB_SW_SUSPEND, "RB_SW_SUSPEND",
|
|
|
|
|
+ scm_from_int (RB_SW_SUSPEND));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_RB_KEXEC, "RB_KEXEC",
|
|
|
|
|
+ scm_from_int (RB_KEXEC));
|
|
|
|
|
+
|
|
|
|
|
+SCM_DEFINE (scm_reboot, "reboot", 0, 1, 0,
|
|
|
|
|
+ (SCM command),
|
|
|
|
|
+ "Reboot the system. @var{command} must be one of the @code{RB_} "
|
|
|
|
|
+ "constants; if omitted, @var{RB_AUTOBOOT} is used, thus "
|
|
|
|
|
+ "performing a hard reset.")
|
|
|
|
|
+#define FUNC_NAME s_scm_reboot
|
|
|
|
|
+{
|
|
|
|
|
+ int c_command;
|
|
|
|
|
+
|
|
|
|
|
+ if (SCM_UNBNDP (command))
|
|
|
|
|
+ c_command = RB_AUTOBOOT;
|
|
|
|
|
+ else
|
|
|
|
|
+ c_command = scm_to_int (command);
|
|
|
|
|
+
|
|
|
|
|
+ reboot (c_command);
|
|
|
|
|
+
|
|
|
|
|
+ return SCM_UNSPECIFIED; /* likely unreached */
|
|
|
|
|
+}
|
|
|
|
|
+#undef FUNC_NAME
|
|
|
|
|
+
|
2013-02-14 23:29:28 +00:00
|
|
|
|
+/* Linux network interfaces. See <linux/if.h>. */
|
|
|
|
|
+
|
|
|
|
|
+#include <linux/if.h>
|
|
|
|
|
+#include <linux/sockios.h>
|
|
|
|
|
+#include "libguile/socket.h"
|
|
|
|
|
+
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_UP, "IFF_UP",
|
|
|
|
|
+ scm_from_int (IFF_UP));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_BROADCAST, "IFF_BROADCAST",
|
|
|
|
|
+ scm_from_int (IFF_BROADCAST));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_DEBUG, "IFF_DEBUG",
|
|
|
|
|
+ scm_from_int (IFF_DEBUG));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_LOOPBACK, "IFF_LOOPBACK",
|
|
|
|
|
+ scm_from_int (IFF_LOOPBACK));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_POINTOPOINT, "IFF_POINTOPOINT",
|
|
|
|
|
+ scm_from_int (IFF_POINTOPOINT));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_NOTRAILERS, "IFF_NOTRAILERS",
|
|
|
|
|
+ scm_from_int (IFF_NOTRAILERS));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_RUNNING, "IFF_RUNNING",
|
|
|
|
|
+ scm_from_int (IFF_RUNNING));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_NOARP, "IFF_NOARP",
|
|
|
|
|
+ scm_from_int (IFF_NOARP));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_PROMISC, "IFF_PROMISC",
|
|
|
|
|
+ scm_from_int (IFF_PROMISC));
|
|
|
|
|
+SCM_VARIABLE_INIT (flag_IFF_ALLMULTI, "IFF_ALLMULTI",
|
|
|
|
|
+ scm_from_int (IFF_ALLMULTI));
|
|
|
|
|
+
|
|
|
|
|
+SCM_DEFINE (scm_set_network_interface_address, "set-network-interface-address",
|
|
|
|
|
+ 3, 0, 0,
|
|
|
|
|
+ (SCM socket, SCM name, SCM address),
|
|
|
|
|
+ "Configure network interface @var{name}.")
|
|
|
|
|
+#define FUNC_NAME s_scm_set_network_interface_address
|
|
|
|
|
+{
|
|
|
|
|
+ char *c_name;
|
|
|
|
|
+ struct ifreq ifr;
|
|
|
|
|
+ struct sockaddr *c_address;
|
|
|
|
|
+ size_t sa_len;
|
|
|
|
|
+ int fd, err;
|
|
|
|
|
+
|
|
|
|
|
+ socket = SCM_COERCE_OUTPORT (socket);
|
|
|
|
|
+ SCM_VALIDATE_OPFPORT (1, socket);
|
|
|
|
|
+ fd = SCM_FPORT_FDES (socket);
|
|
|
|
|
+
|
|
|
|
|
+ memset (&ifr, 0, sizeof ifr);
|
|
|
|
|
+ c_name = scm_to_locale_string (name);
|
|
|
|
|
+ c_address = scm_to_sockaddr (address, &sa_len);
|
|
|
|
|
+
|
|
|
|
|
+ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1);
|
|
|
|
|
+ memcpy (&ifr.ifr_addr, c_address, sa_len);
|
|
|
|
|
+
|
|
|
|
|
+ err = ioctl (fd, SIOCSIFADDR, &ifr);
|
|
|
|
|
+ if (err != 0)
|
|
|
|
|
+ err = errno;
|
|
|
|
|
+
|
|
|
|
|
+ free (c_name);
|
|
|
|
|
+ free (c_address);
|
|
|
|
|
+
|
|
|
|
|
+ if (err != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ errno = err;
|
|
|
|
|
+ SCM_SYSERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return SCM_UNSPECIFIED;
|
|
|
|
|
+}
|
|
|
|
|
+#undef FUNC_NAME
|
|
|
|
|
+
|
|
|
|
|
+SCM_DEFINE (scm_set_network_interface_flags, "set-network-interface-flags",
|
|
|
|
|
+ 3, 0, 0,
|
|
|
|
|
+ (SCM socket, SCM name, SCM flags),
|
|
|
|
|
+ "Change the flags of network interface @var{name} to "
|
|
|
|
|
+ "@var{flags}.")
|
|
|
|
|
+#define FUNC_NAME s_scm_set_network_interface_flags
|
|
|
|
|
+{
|
|
|
|
|
+ struct ifreq ifr;
|
|
|
|
|
+ char *c_name;
|
|
|
|
|
+ int fd, err;
|
|
|
|
|
+
|
|
|
|
|
+ socket = SCM_COERCE_OUTPORT (socket);
|
|
|
|
|
+ SCM_VALIDATE_OPFPORT (1, socket);
|
|
|
|
|
+ fd = SCM_FPORT_FDES (socket);
|
|
|
|
|
+
|
|
|
|
|
+ memset (&ifr, 0, sizeof ifr);
|
|
|
|
|
+ c_name = scm_to_locale_string (name);
|
|
|
|
|
+ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1);
|
|
|
|
|
+ ifr.ifr_flags = scm_to_short (flags);
|
|
|
|
|
+
|
|
|
|
|
+ err = ioctl (fd, SIOCSIFFLAGS, &ifr);
|
|
|
|
|
+ if (err != 0)
|
|
|
|
|
+ err = errno;
|
|
|
|
|
+
|
|
|
|
|
+ free (c_name);
|
|
|
|
|
+
|
|
|
|
|
+ if (err != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ errno = err;
|
|
|
|
|
+ SCM_SYSERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return SCM_UNSPECIFIED;
|
|
|
|
|
+}
|
|
|
|
|
+#undef FUNC_NAME
|
|
|
|
|
+
|
|
|
|
|
+SCM_DEFINE (scm_network_interface_flags, "network-interface-flags",
|
|
|
|
|
+ 2, 0, 0,
|
|
|
|
|
+ (SCM socket, SCM name),
|
|
|
|
|
+ "Return the flags of network interface @var{name}.")
|
|
|
|
|
+#define FUNC_NAME s_scm_network_interface_flags
|
|
|
|
|
+{
|
|
|
|
|
+ struct ifreq ifr;
|
|
|
|
|
+ char *c_name;
|
|
|
|
|
+ int fd, err;
|
|
|
|
|
+
|
|
|
|
|
+ socket = SCM_COERCE_OUTPORT (socket);
|
|
|
|
|
+ SCM_VALIDATE_OPFPORT (1, socket);
|
|
|
|
|
+ fd = SCM_FPORT_FDES (socket);
|
|
|
|
|
+
|
|
|
|
|
+ memset (&ifr, 0, sizeof ifr);
|
|
|
|
|
+ c_name = scm_to_locale_string (name);
|
|
|
|
|
+ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1);
|
|
|
|
|
+
|
|
|
|
|
+ err = ioctl (fd, SIOCGIFFLAGS, &ifr);
|
|
|
|
|
+ if (err != 0)
|
|
|
|
|
+ err = errno;
|
|
|
|
|
+
|
|
|
|
|
+ free (c_name);
|
|
|
|
|
+
|
|
|
|
|
+ if (err != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ errno = err;
|
|
|
|
|
+ SCM_SYSERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return scm_from_short (ifr.ifr_flags);
|
|
|
|
|
+}
|
|
|
|
|
+#undef FUNC_NAME
|
2015-05-23 19:10:34 +00:00
|
|
|
|
+#endif
|
2013-02-14 23:29:28 +00:00
|
|
|
|
+
|
|
|
|
|
void
|
|
|
|
|
scm_init_posix ()
|
|
|
|
|
{
|
2015-05-23 19:10:34 +00:00
|
|
|
|
--
|
|
|
|
|
2.4.1
|