SPDX: Mass-update to GPL-2.0-or-later
[exim.git] / src / src / os.c
index 6e02b8fe298099e96323d39d435ab63107f3c189..fc29f176605beee3db24f98cf5888610813375ce 100644 (file)
@@ -2,13 +2,20 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) The Exim Maintainers 2021 - 2022 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 #ifdef STAND_ALONE
-#include <signal.h>
-#include <stdio.h>
-#include <time.h>
+# include <signal.h>
+# include <stdio.h>
+# include <time.h>
+#endif
+
+#ifndef CS
+# define CS (char *)
+# define US (unsigned char *)
 #endif
 
 /* This source file contains "default" system-dependent functions which
@@ -413,7 +420,7 @@ if (avg_kd < 0)
   }
 
 if (lseek (avg_kd, avg_offset, 0) == -1L
-    || read (avg_kd, (char *)(&avg), sizeof (avg)) != sizeof(avg))
+    || read (avg_kd, CS (&avg), sizeof (avg)) != sizeof(avg))
   return -1;
 
 return (int)(((double)avg/FSCALE)*1000.0);
@@ -488,12 +495,13 @@ if (getifaddrs(&ifalist) != 0)
   log_write(0, LOG_PANIC_DIE, "Unable to call getifaddrs: %d %s",
     errno, strerror(errno));
 
-struct ifaddrs *ifa;
-for (ifa = ifalist; ifa != NULL; ifa = ifa->ifa_next)
+for (struct ifaddrs * ifa = ifalist; ifa; ifa = ifa->ifa_next)
   {
-  if (ifa->ifa_addr->sa_family != AF_INET
+  struct sockaddr * ifa_addr = ifa->ifa_addr;
+  if (!ifa_addr) continue;
+  if (ifa_addr->sa_family != AF_INET
 #if HAVE_IPV6
-    && ifa->ifa_addr->sa_family != AF_INET6
+    && ifa_addr->sa_family != AF_INET6
 #endif /* HAVE_IPV6 */
     )
     continue;
@@ -504,12 +512,12 @@ for (ifa = ifalist; ifa != NULL; ifa = ifa->ifa_next)
   /* Create a data block for the address, fill in the data, and put it on the
   chain. */
 
-  next = store_get(sizeof(ip_address_item));
+  next = store_get(sizeof(ip_address_item), GET_UNTAINTED);
   next->next = NULL;
   next->port = 0;
-  (void)host_ntoa(-1, ifa->ifa_addr, next->address, NULL);
+  (void)host_ntoa(-1, ifa_addr, next->address, NULL);
 
-  if (yield == NULL)
+  if (!yield)
     yield = last = next;
   else
     {
@@ -612,7 +620,6 @@ int vs;
 ip_address_item *yield = NULL;
 ip_address_item *last = NULL;
 ip_address_item  *next;
-char *cp;
 char buf[MAX_INTERFACES*sizeof(struct V_ifreq)];
 struct sockaddr *addrp;
 size_t len = 0;
@@ -645,7 +652,7 @@ ifc.V_ifc_family = V_FAMILY_QUERY;
 ifc.V_ifc_flags = 0;
 #endif
 
-if (ioctl(vs, V_GIFCONF, (char *)&ifc) < 0)
+if (ioctl(vs, V_GIFCONF, CS &ifc) < 0)
   log_write(0, LOG_PANIC_DIE, "Unable to get interface configuration: %d %s",
     errno, strerror(errno));
 
@@ -678,9 +685,9 @@ buffer is not guaranteed to be aligned. Thus, we must first copy the basic
 struct to some aligned memory before looking at the field in the fixed part to
 find its length, and then recopy the correct length. */
 
-for (cp = buf; cp < buf + ifc.V_ifc_len; cp += len)
+for (char * cp = buf; cp < buf + ifc.V_ifc_len; cp += len)
   {
-  memcpy((char *)&ifreq, cp, sizeof(ifreq));
+  memcpy(CS &ifreq, cp, sizeof(ifreq));
 
   #ifndef HAVE_SA_LEN
   len = sizeof(struct V_ifreq);
@@ -710,7 +717,7 @@ for (cp = buf; cp < buf + ifc.V_ifc_len; cp += len)
   interface hasn't been "plumbed" to any protocol (IPv4 or IPv6). Therefore,
   we now just treat this case as "down" as well. */
 
-  if (ioctl(vs, V_GIFFLAGS, (char *)&ifreq) < 0)
+  if (ioctl(vs, V_GIFFLAGS, CS &ifreq) < 0)
     {
     continue;
     /*************
@@ -726,7 +733,7 @@ for (cp = buf; cp < buf + ifc.V_ifc_len; cp += len)
   GIFFLAGS may have wrecked the data. */
 
   #ifndef SIOCGIFCONF_GIVES_ADDR
-  if (ioctl(vs, V_GIFADDR, (char *)&ifreq) < 0)
+  if (ioctl(vs, V_GIFADDR, CS &ifreq) < 0)
     log_write(0, LOG_PANIC_DIE, "Unable to get IP address for %s interface: "
       "%d %s", ifreq.V_ifr_name, errno, strerror(errno));
   addrp = &ifreq.V_ifr_addr;
@@ -740,7 +747,7 @@ for (cp = buf; cp < buf + ifc.V_ifc_len; cp += len)
   /* Create a data block for the address, fill in the data, and put it on the
   chain. */
 
-  next = store_get(sizeof(ip_address_item));
+  next = store_get(sizeof(ip_address_item), GET_UNTAINTED);
   next->next = NULL;
   next->port = 0;
   (void)host_ntoa(-1, addrp, next->address, NULL);
@@ -772,13 +779,13 @@ interfaces. We just return the loopback address(es). */
 ip_address_item *
 os_common_find_running_interfaces(void)
 {
-ip_address_item *yield = store_get(sizeof(address_item));
+ip_address_item *yield = store_get(sizeof(address_item), GET_UNTAINTED);
 yield->address = US"127.0.0.1";
 yield->port = 0;
 yield->next = NULL;
 
 #if HAVE_IPV6
-yield->next = store_get(sizeof(address_item));
+yield->next = store_get(sizeof(address_item), GET_UNTAINTED);
 yield->next->address = US"::1";
 yield->next->port = 0;
 yield->next->next = NULL;
@@ -828,14 +835,62 @@ return type.
 res_state
 os_get_dns_resolver_res(void)
 {
-  return &_res;
+return &_res;
 }
 
 #endif /* OS_GET_DNS_RESOLVER_RES */
 
+/* ----------------------------------------------------------------------- */
+
+/***********************************************************
+*                 unsetenv()                               *
+***********************************************************/
+
+/* Most modern systems define int unsetenv(const char*),
+* some don't. */
+
+#if !defined(OS_UNSETENV)
+int
+os_unsetenv(const unsigned char * name)
+{
+return unsetenv(CS name);
+}
+#endif
 
 /* ----------------------------------------------------------------------- */
 
+/***********************************************************
+*               getcwd()                                   *
+***********************************************************/
+
+/* Glibc allows getcwd(NULL, 0) to do auto-allocation. Some systems
+do auto-allocation, but need the size of the buffer, and others
+may not even do this. If the OS supports getcwd(NULL, 0) we'll use
+this, for all other systems we provide our own getcwd() */
+
+#if !defined(OS_GETCWD)
+unsigned char *
+os_getcwd(unsigned char * buffer, size_t size)
+{
+return US  getcwd(CS buffer, size);
+}
+#else
+#ifndef PATH_MAX
+# define PATH_MAX 4096
+#endif
+unsigned char *
+os_getcwd(unsigned char * buffer, size_t size)
+{
+char * b = CS buffer;
+
+if (!size) size = PATH_MAX;
+if (!b && !(b = malloc(size))) return NULL;
+if (!(b = getcwd(b, size))) return NULL;
+return buffer ? buffer : realloc(b, strlen(b) + 1);
+}
+#endif
+
+/* ----------------------------------------------------------------------- */
 
 
 
@@ -869,7 +924,7 @@ int rc;
 printf("Testing restarting signal; wait for handler message, then type a line\n");
 strcpy(buffer, "*** default ***\n");
 os_restarting_signal(SIGALRM, sigalrm_handler);
-alarm(2);
+ALARM(2);
 if ((rc = read(fd, buffer, sizeof(buffer))) < 0)
   printf("No data read\n");
 else
@@ -877,12 +932,12 @@ else
   buffer[rc] = 0;
   printf("Read: %s", buffer);
   }
-alarm(0);
+ALARM_CLR(0);
 
 printf("Testing non-restarting signal; should read no data after handler message\n");
 strcpy(buffer, "*** default ***\n");
 os_non_restarting_signal(SIGALRM, sigalrm_handler);
-alarm(2);
+ALARM(2);
 if ((rc = read(fd, buffer, sizeof(buffer))) < 0)
   printf("No data read\n");
 else
@@ -890,7 +945,7 @@ else
   buffer[rc] = 0;
   printf("Read: %s", buffer);
   }
-alarm(0);
+ALARM_CLR(0);
 
 printf("Testing load averages (last test - ^C to kill)\n");
 for (;;)