Пример #1
0
ph_hook_point_t *ph_hook_point_get(ph_string_t *name, bool create)
{
  ph_hook_point_t *hp = 0;

  ck_rwlock_read_lock(&rwlock);
  {
    ph_ht_lookup(&hook_hash, &name, &hp, false);
  }
  ck_rwlock_read_unlock(&rwlock);

  if (hp || !create) {
    return hp;
  }

  ck_rwlock_write_lock(&rwlock);
  {
    // Look again: someone may have populated while we were unlocked
    ph_ht_lookup(&hook_hash, &name, &hp, false);
    if (!hp) {
      hp = ph_mem_alloc(mt.hookpoint);
      if (hp) {
        if (ph_ht_set(&hook_hash, &name, &hp) != PH_OK) {
          ph_mem_free(mt.hookpoint, hp);
          hp = NULL;
        }
      }
    }
  }
  ck_rwlock_write_unlock(&rwlock);

  return hp;
}
Пример #2
0
// Called when an ARES socket is ready
static void process_ares(ph_job_t *job, ph_iomask_t why, void *data)
{
  ph_dns_channel_t *chan = data;
  ares_socket_t fd;
  ares_socket_t rfd = ARES_SOCKET_BAD;
  ares_socket_t wfd = ARES_SOCKET_BAD;

  fd = job->fd;

  if (why & PH_IOMASK_READ) {
    rfd = job->fd;
  }
  if (why & PH_IOMASK_WRITE) {
    wfd = job->fd;
  }

  pthread_mutex_lock(&chan->chanlock);
  ares_process_fd(chan->chan, rfd, wfd);
  if (ph_ht_lookup(&chan->sock_map, &fd, &job, false) == PH_OK &&
      ph_job_get_kmask(job) == 0) {
    // Didn't delete it, but didn't reschedule it, so do that now
    apply_mask(chan, job,
        job->mask ? job->mask : PH_IOMASK_READ);
  }
  pthread_mutex_unlock(&chan->chanlock);
}
Пример #3
0
/* called when ares wants to change the event mask */
static void sock_state_cb(void *data, ares_socket_t socket_fd,
                          int readable, int writable)
{
  ph_dns_channel_t *chan = data;
  ph_job_t *job;
  ph_iomask_t mask = 0;

  if (readable) {
    mask |= PH_IOMASK_READ;
  }
  if (writable) {
    mask |= PH_IOMASK_WRITE;
  }

  if (ph_ht_lookup(&chan->sock_map, &socket_fd, &job, false) != PH_OK) {
    ph_panic("job for socket %d was not found in ares sock_state_cb",
        socket_fd);
  }

  if (mask) {
    apply_mask(chan, job, mask);
  } else {
    ph_job_set_nbio(job, 0, NULL);
    // We're done with this guy, remove it
    ph_ht_del(&chan->sock_map, &socket_fd);
    ph_mem_free(mt.job, job);
  }
}
Пример #4
0
ph_variant_t *ph_var_object_get(ph_variant_t *obj, ph_string_t *key)
{
  ph_result_t res;
  ph_variant_t *val;

  if (obj->type != PH_VAR_OBJECT) {
    return 0;
  }

  res = ph_ht_lookup(&obj->u.oval, &key, &val, false);
  if (res != PH_OK) {
    return 0;
  }

  return val;
}
Пример #5
0
int
ph_vprintf_core(void *print_arg,
    const struct ph_vprintf_funcs *print_funcs,
    const char *fmt0, va_list ap)
{
  char *fmt;    /* format string */
  int ch;     /* character from fmt */
  int n, n2;    /* handy integers (short term usage) */
  char *cp;   /* handy char pointer (short term usage) */
  int flags;    /* flags as above */
  int ret;    /* return value accumulator */
  int width;    /* width from format (%8d), or 0 */
  int prec;   /* precision from format; <0 for N/A */
  char sign;    /* sign prefix (' ', '+', '-', or \0) */
  wchar_t wc;
  mbstate_t ps;
#ifdef FLOATING_POINT
  /*
   * We can decompose the printed representation of floating
   * point numbers into several parts, some of which may be empty:
   *
   * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
   *    A       B     ---C---      D       E   F
   *
   * A: 'sign' holds this value if present; '\0' otherwise
   * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
   * C: cp points to the string MMMNNN.  Leading and trailing
   *  zeros are not in the string and must be added.
   * D: expchar holds this character; '\0' if no exponent, e.g. %f
   * F: at least two digits for decimal, at least one digit for hex
   */
  const char *decimal_point =
#ifdef USE_LOCALE
    NULL
#else
    "."
#endif
    ;
  int signflag;   /* true if float is negative */
  union {     /* floating point arguments %[aAeEfFgG] */
    double dbl;
    long double ldbl;
  } fparg;
  int expt;   /* integer value of exponent */
  char expchar = 0;   /* exponent character: [eEpP\0] */
  char *dtoaend;    /* pointer to end of converted digits */
  int expsize = 0;    /* character count for expstr */
  int lead = 0;   /* sig figs before decimal or group sep */
  int ndig = 0;   /* actual number of digits returned by dtoa */
  char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
  char *dtoaresult = NULL;
#endif

  uintmax_t _umax;  /* integer arguments %[diouxX] */
  enum { OCT, DEC, HEX } base;  /* base for %[diouxX] conversion */
  int dprec;    /* a copy of prec if %[diouxX], 0 otherwise */
  int realsz;   /* field size expanded by dprec */
  int size;   /* size of converted field or string */
  const char *xdigs = xdigs_lower;  /* digits for %[xX] conversion */
  char buf[BUF];    /* buffer with space for digits of uintmax_t */
  char ox[2];   /* space for 0x; ox[1] is either x, X, or \0 */
  union arg *argtable;  /* args, built due to positional arg */
  union arg statargtable[STATIC_ARG_TBL_SIZE];
  size_t argtablesiz;
  int nextarg;    /* 1-based argument index */
  va_list orgap;    /* original argument pointer */
#ifdef PRINTF_WIDE_CHAR
  char *convbuf;    /* buffer for wide to multi-byte conversion */
#endif

  bool print_error = false;

  /*
   * BEWARE, these `goto error' on error, and PAD uses `n'.
   */
#define PRINT(ptr, len) do { \
  if (len > 0 && !print_funcs->print(print_arg, ptr, len)) { \
    print_error = true; \
    goto error; \
  } \
} while (0)
#define PAD(howmany, with) do { \
  if ((n = (howmany)) > 0) { \
    while (n > PADSIZE) { \
      PRINT(with, PADSIZE); \
      n -= PADSIZE; \
    } \
    PRINT(with, n); \
  } \
} while (0)
#define PRINTANDPAD(p, ep, len, with) do {  \
  n2 = (ep) - (p);            \
  if (n2 > (len))       \
    n2 = (len);     \
  if (n2 > 0)       \
    PRINT((p), n2);     \
  PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
} while(0)
#define FLUSH() do { \
  if (print_funcs->flush && !print_funcs->flush(print_arg)) { \
    print_error = true; \
    goto error; \
  } \
} while (0)

  /*
   * To extend shorts properly, we need both signed and unsigned
   * argument extraction methods.
   */
#define SARG() \
  ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
      flags&LLONGINT ? GETARG(long long) : \
      flags&LONGINT ? GETARG(long) : \
      flags&PTRINT ? GETARG(ptrdiff_t) : \
      flags&SIZEINT ? GETARG(ssize_t) : \
      flags&SHORTINT ? (short)GETARG(int) : \
      flags&CHARINT ? (__signed char)GETARG(int) : \
      GETARG(int)))
#define UARG() \
  ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
      flags&LLONGINT ? GETARG(unsigned long long) : \
      flags&LONGINT ? GETARG(unsigned long) : \
      flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
      flags&SIZEINT ? GETARG(size_t) : \
      flags&SHORTINT ? (unsigned short)GETARG(int) : \
      flags&CHARINT ? (unsigned char)GETARG(int) : \
      GETARG(unsigned int)))

  /*
   * Append a digit to a value and check for overflow.
   */
#define APPEND_DIGIT(val, dig) do { \
  if ((val) > INT_MAX / 10) \
    goto overflow; \
  (val) *= 10; \
  if ((val) > INT_MAX - to_digit((dig))) \
    goto overflow; \
  (val) += to_digit((dig)); \
} while (0)

   /*
    * Get * arguments, including the form *nn$.  Preserve the nextarg
    * that the argument can be gotten once the type is determined.
    */
#define GETASTER(val) \
  n2 = 0; \
  cp = fmt; \
  while (is_digit(*cp)) { \
    APPEND_DIGIT(n2, *cp); \
    cp++; \
  } \
  if (*cp == '$') { \
    int hold = nextarg; \
    if (argtable == NULL) { \
      argtable = statargtable; \
      __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
    } \
    nextarg = n2; \
    val = GETARG(int); \
    nextarg = hold; \
    fmt = ++cp; \
  } else { \
    val = GETARG(int); \
  }

/*
* Get the argument indexed by nextarg.   If the argument table is
* built, use it to get the argument.  If its not, get the next
* argument (and arguments must be gotten sequentially).
*/
#define GETARG(type) \
  ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
    (nextarg++, va_arg(ap, type)))

  fmt = (char *)fmt0;
  argtable = NULL;
  nextarg = 1;
  va_copy(orgap, ap);
  ret = 0;
#ifdef PRINTF_WIDE_CHAR
  convbuf = NULL;
#endif

  memset(&ps, 0, sizeof(ps));
  /*
   * Scan the format for conversions (`%' character).
   */
  for (;;) {
    cp = fmt;
    while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
      fmt += n;
      if (wc == '%' || wc == '`') {
        fmt--;
        break;
      }
    }
    if (fmt != cp) {
      ptrdiff_t m = fmt - cp;
      if (m < 0 || m > INT_MAX - ret)
        goto overflow;
      PRINT(cp, m);
      ret += m;
    }
    if (n <= 0)
      goto done;

    flags = 0;
    dprec = 0;
    width = 0;
    prec = -1;
    sign = '\0';
    ox[1] = '\0';

    /* check for phenom specials */
    if (fmt[0] == '`') {
      if (fmt[1] == '`') {
        /* we just print a literal ` */
        PRINT(fmt, 1);
        fmt += 2;
        continue;
      }
      if (fmt[1] != 'P') {
        /* some regular backtick enclosed text */
        PRINT(fmt, 1);
        fmt++;
        continue;
      }
      switch (fmt[2]) {
        case '{':
          {
            char *term;
            void *object;
            struct formatter *f = NULL;
            ph_string_t key, *keyptr = &key;

            fmt += 3;
            term = strstr(fmt, ":%p}");
            if (!term) {
              break;
            }

            object = GETARG(void*);

            pthread_once(&once_init, init_vprintf);
            ph_string_init_claim(&key, PH_STRING_STATIC, fmt,
                term - fmt, term - fmt);

            pthread_rwlock_rdlock(&formatter_lock);
            ph_ht_lookup(&formatters, &keyptr, (void*)&f, false);
            pthread_rwlock_unlock(&formatter_lock);

            if (f && f->func) {
              ret += f->func(f->farg, object, print_arg, print_funcs);
            } else {
              PRINT("INVALID:", 8);
              PRINT(fmt, term - fmt);
              ret += 8 + (term - fmt);
            }

            fmt = term + 4;
            continue;
          }

        case 'e':
          /* "`Pe%d" errno formatted as string */
          if (fmt[3] == '%' && fmt[4] == 'd') {
            char ebuf[128];
            int err = GETARG(int);

            cp = (char*)ph_strerror_r(err, ebuf, sizeof(ebuf));

            size = strlen(cp);
            fmt += 5;
            PRINT(cp, size);
            ret += size;
            continue;
          }
          break;

        case 's': {
          uint32_t len;
          ph_string_t *str = NULL;

          if (!memcmp("%p", fmt + 3, 2)) {
            str = GETARG(void*);
            len = str->len;
            fmt += 5;
          } else if (!memcmp("%d%p", fmt + 3, 4)) {
            len = GETARG(int);
            str = GETARG(void*);
            len = MIN(len, str->len);
            fmt += 7;
          } else {
            // invalid
            break;