view lib/portability.c @ 1613:96aa7ec74936 draft

Fix yet another sed bug. The s/// command would copy the \ of substitutions before deciding what to do with them (generally overwriting the \ with the new data). When the substitution was A) at the very end of the new string, B) resolved to nothing, it could leave a trailing \ that didn't belong there and didn't get overwritten because the "copy trailing data" part that copies the original string's null terminator already happened before the \ overwrote it. The ghostwheel() function restarts regexes after embedded NUL bytes, but if the string it's passed is _longer_ than the length it's told then it gets confused (and it means we're off the end of our allocation so segfaults are likely). Fix: test for \ first and move the "copy byte" logic into an else case.
author Rob Landley <rob@landley.net>
date Mon, 15 Dec 2014 03:34:55 -0600
parents ce22ad7a26c1
children aafd2f28245a
line wrap: on
line source

/* portability.c - code to workaround the deficiencies of various platforms.
 *
 * Copyright 2012 Rob Landley <rob@landley.net>
 * Copyright 2012 Georgi Chorbadzhiyski <gf@unixsol.org>
 */

#include "toys.h"

#if !defined(__uClinux__)
pid_t xfork(void)
{
  pid_t pid = fork();

  if (pid < 0) perror_exit("fork");

  return pid;
}
#endif

#if defined(__APPLE__)
ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream)
{
  int ch;
  size_t new_len;
  ssize_t i = 0;
  char *line, *new_line;

  // Invalid input
  if (!linep || !np) {
    errno = EINVAL;
    return -1;
  }

  if (*linep == NULL || *np == 0) {
    *np = 1024;
    *linep = calloc(1, *np);
    if (*linep == NULL) return -1;
  }
  line = *linep;

  while ((ch = getc(stream)) != EOF) {
    if (i > *np) {
      // Need more space
      new_len = *np + 1024;
      new_line = realloc(*linep, new_len);
      if (!new_line) return -1;
      *np = new_len;
      *linep = new_line;
    }

    line[i] = ch;
    if (ch == delim) break;
    i += 1;
  }

  if (i > *np) {
    // Need more space
    new_len  = i + 2;
    new_line = realloc(*linep, new_len);
    if (!new_line) return -1;
    *np = new_len;
    *linep = new_line;
  }
  line[i + 1] = '\0';

  return i > 0 ? i : -1;
}

ssize_t getline(char **linep, size_t *np, FILE *stream)
{
  return getdelim(linep, np, '\n', stream);
}

extern char **environ;

int clearenv(void)
{
  *environ = NULL;
  return 0;
}
#endif