static void readUnlock(skipList list, skipItem x, void **plock) { int startFlush = FALSE; if(list->threaded) mLock(&list->read); if(plock) { x->locks++; *plock = x; } if(! list->threaded) return; list->readers--; if((list->readers == 0) && list->block) startFlush = TRUE; mUnlock(&list->read); if(startFlush) cSignal(&list->flush); return; }
static void readUnblock(skipList list) { list->block = FALSE; mUnlock(&list->read); cBroadcast(&list->resume); return; }
NEOERR *nerr_init (void) { NEOERR *err; if (Inited == 0) { #ifdef HAVE_PTHREADS /* In threaded environments, we have to mutex lock to do this init, but * we don't want to use a mutex every time to check that it was Inited. * So, we only lock if our first test of Inited was false */ err = mLock(&InitLock); if (err != STATUS_OK) return nerr_pass(err); if (Inited == 0) { #endif err = uListInit (&Errors, 10, 0); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_PASS, "InternalPass"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_ASSERT, "AssertError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_NOT_FOUND, "NotFoundError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_DUPLICATE, "DuplicateError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_NOMEM, "MemoryError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_PARSE, "ParseError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_OUTOFRANGE, "RangeError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_SYSTEM, "SystemError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_IO, "IOError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_LOCK, "LockError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_DB, "DBError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_EXISTS, "ExistsError"); if (err != STATUS_OK) return nerr_pass(err); err = nerr_register (&NERR_MAX_RECURSION, "MaxRecursionError"); if (err != STATUS_OK) return nerr_pass(err); Inited = 1; #ifdef HAVE_PTHREADS } err = mUnlock(&InitLock); if (err != STATUS_OK) return nerr_pass(err); #endif } return STATUS_OK; }
static void readLock(skipList list) { mLock(&list->read); if(list->block) cWait(&list->resume, &list->read); list->readers++; mUnlock(&list->read); return; }
void skipRelease(skipList list, void *lock) { skipItem x; mLock(&list->read); x = lock; x->locks--; mUnlock(&list->read); return; }
static NEOERR *split_and_convert (const char *src, int slen, STRING *out, HTML_CONVERT_OPTS *opts) { NEOERR *err = STATUS_OK; regmatch_t email_match, url_match; int errcode; char *ptr, *esc; char errbuf[256]; struct _parts *parts; int part_count; int part; int x, i; int spaces = 0; if (!CompiledRe) { #ifdef HAVE_PTHREADS /* In threaded environments, we have to mutex lock to do this regcomp, but * we don't want to use a mutex every time to check that it was regcomp. * So, we only lock if our first test of compiled was false */ err = mLock(&InitLock); if (err != STATUS_OK) return nerr_pass(err); if (CompiledRe == 0) { #endif if ((errcode = regcomp (&EmailRegex, EmailRe, REG_ICASE | REG_EXTENDED))) { regerror (errcode, &EmailRegex, errbuf, sizeof(errbuf)); err = nerr_raise (NERR_PARSE, "Unable to compile EmailRE: %s", errbuf); } if ((errcode = regcomp (&UrlRegex, URLRe, REG_ICASE | REG_EXTENDED))) { regerror (errcode, &UrlRegex, errbuf, sizeof(errbuf)); err = nerr_raise (NERR_PARSE, "Unable to compile URLRe: %s", errbuf); } CompiledRe = 1; #ifdef HAVE_PTHREADS } if (err) { mUnlock(&InitLock); return err; } err = mUnlock(&InitLock); if (err != STATUS_OK) return nerr_pass(err); #else if (err) { return err; } #endif } part_count = 20; parts = (struct _parts *) malloc (sizeof(struct _parts) * part_count); part = 0; x = 0; if (regexec (&EmailRegex, src+x, 1, &email_match, 0) != 0) { email_match.rm_so = -1; email_match.rm_eo = -1; } else { email_match.rm_so += x; email_match.rm_eo += x; } if (regexec (&UrlRegex, src+x, 1, &url_match, 0) != 0) { url_match.rm_so = -1; url_match.rm_eo = -1; } else { url_match.rm_so += x; url_match.rm_eo += x; } while ((x < slen) && !((email_match.rm_so == -1) && (url_match.rm_so == -1))) { if (part >= part_count) { void *new_ptr; part_count *= 2; new_ptr = realloc (parts, sizeof(struct _parts) * part_count); if (new_ptr == NULL) { free(parts); return nerr_raise (NERR_NOMEM, "Unable to increase url matcher to %d urls", part_count); } parts = (struct _parts *) new_ptr; } if ((url_match.rm_so != -1) && ((email_match.rm_so == -1) || (url_match.rm_so <= email_match.rm_so))) { parts[part].begin = url_match.rm_so; parts[part].end = url_match.rm_eo; parts[part].type = SC_TYPE_URL; x = parts[part].end + 1; part++; if (x < slen) { if (regexec (&UrlRegex, src+x, 1, &url_match, 0) != 0) { url_match.rm_so = -1; url_match.rm_eo = -1; } else { url_match.rm_so += x; url_match.rm_eo += x; } if ((email_match.rm_so != -1) && (x > email_match.rm_so)) { if (regexec (&EmailRegex, src+x, 1, &email_match, 0) != 0) { email_match.rm_so = -1; email_match.rm_eo = -1; } else { email_match.rm_so += x; email_match.rm_eo += x; } } } } else { parts[part].begin = email_match.rm_so; parts[part].end = email_match.rm_eo; parts[part].type = SC_TYPE_EMAIL; x = parts[part].end + 1; part++; if (x < slen) { if (regexec (&EmailRegex, src+x, 1, &email_match, 0) != 0) { email_match.rm_so = -1; email_match.rm_eo = -1; } else { email_match.rm_so += x; email_match.rm_eo += x; } if ((url_match.rm_so != -1) && (x > url_match.rm_so)) { if (regexec (&UrlRegex, src+x, 1, &url_match, 0) != 0) { url_match.rm_so = -1; url_match.rm_eo = -1; } else { url_match.rm_so += x; url_match.rm_eo += x; } } } } } i = 0; x = 0; while (x < slen) { if ((i >= part) || (x < parts[i].begin)) { ptr = strpbrk(src + x, "&<>\r\n "); if (ptr == NULL) { if (spaces) { int sp; for (sp = 0; sp < spaces - 1; sp++) { err = string_append (out, " "); if (err != STATUS_OK) break; } if (err != STATUS_OK) break; err = string_append_char (out, ' '); } spaces = 0; if (i < part) { err = string_appendn (out, src + x, parts[i].begin - x); x = parts[i].begin; } else { err = string_append (out, src + x); x = slen; } } else { if ((i >= part) || ((ptr - src) < parts[i].begin)) { if (spaces) { int sp; for (sp = 0; sp < spaces - 1; sp++) { err = string_append (out, " "); if (err != STATUS_OK) break; } if (err != STATUS_OK) break; err = string_append_char (out, ' '); } spaces = 0; err = string_appendn (out, src + x, (ptr - src) - x); if (err != STATUS_OK) break; x = ptr - src; if (src[x] == ' ') { if (opts->space_convert) { spaces++; } else err = string_append_char (out, ' '); } else { if (src[x] != '\n' && spaces) { int sp; for (sp = 0; sp < spaces - 1; sp++) { err = string_append (out, " "); if (err != STATUS_OK) break; } if (err != STATUS_OK) break; err = string_append_char (out, ' '); } spaces = 0; if (src[x] == '&') err = string_append (out, "&"); else if (src[x] == '<') err = string_append (out, "<"); else if (src[x] == '>') err = string_append (out, ">"); else if (src[x] == '\n') if (opts->newlines_convert) err = string_append (out, "<br/>\n"); else if (x && src[x-1] == '\n') err = string_append (out, "<p/>\n"); else err = string_append_char (out, '\n'); else if (src[x] != '\r') err = nerr_raise (NERR_ASSERT, "src[x] == '%c'", src[x]); } x++; } else { if (spaces) { int sp; for (sp = 0; sp < spaces - 1; sp++) { err = string_append (out, " "); if (err != STATUS_OK) break; } if (err != STATUS_OK) break; err = string_append_char (out, ' '); } spaces = 0; err = string_appendn (out, src + x, parts[i].begin - x); x = parts[i].begin; } } } else { if (spaces) { int sp; for (sp = 0; sp < spaces - 1; sp++) { err = string_append (out, " "); if (err != STATUS_OK) break; } if (err != STATUS_OK) break; err = string_append_char (out, ' '); } spaces = 0; if (parts[i].type == SC_TYPE_URL) { char last_char = src[parts[i].end-1]; int suffix=0; if (last_char == '.' || last_char == ',') { suffix=1; } err = string_append (out, " <a "); if (err != STATUS_OK) break; if (opts->url_class) { err = string_appendf (out, "class=%s ", opts->url_class); if (err) break; } if (opts->url_target) { err = string_appendf (out, "target=\"%s\" ", opts->url_target); if (err) break; } err = string_append(out, "href=\""); if (err) break; if (opts->bounce_url) { char *url, *esc_url, *new_url; int url_len; if (!strncasecmp(src + x, "www.", 4)) { url_len = 7 + parts[i].end - x - suffix; url = (char *) malloc(url_len+1); if (url == NULL) { err = nerr_raise(NERR_NOMEM, "Unable to allocate memory to convert url"); break; } strcpy(url, "http://"); strncat(url, src + x, parts[i].end - x - suffix); } else { url_len = parts[i].end - x - suffix; url = (char *) malloc(url_len+1); if (url == NULL) { err = nerr_raise(NERR_NOMEM, "Unable to allocate memory to convert url"); break; } strncpy(url, src + x, parts[i].end - x - suffix); url[url_len] = '\0'; } err = cgi_url_escape(url, &esc_url); free(url); if (err) { free(esc_url); break; } new_url = sprintf_alloc(opts->bounce_url, esc_url); free(esc_url); if (new_url == NULL) { err = nerr_raise(NERR_NOMEM, "Unable to allocate memory to convert url"); break; } err = string_append (out, new_url); free(new_url); if (err) break; } else { if (!strncasecmp(src + x, "www.", 4)) { err = string_append (out, "http://"); if (err != STATUS_OK) break; } err = string_appendn (out, src + x, parts[i].end - x - suffix); if (err != STATUS_OK) break; } err = string_append (out, "\">"); if (err != STATUS_OK) break; if (opts->link_name) { err = html_escape_alloc((opts->link_name), strlen(opts->link_name), &esc); } else { err = html_escape_alloc((src + x), parts[i].end - x - suffix, &esc); } if (err != STATUS_OK) break; err = string_append (out, esc); free(esc); if (err != STATUS_OK) break; err = string_append (out, "</a>"); if (suffix) { err = string_appendn(out,src + parts[i].end - 1,1); if (err != STATUS_OK) break; } } else /* type == SC_TYPE_EMAIL */ { err = string_append (out, "<a "); if (err != STATUS_OK) break; if (opts->mailto_class) { err = string_appendf (out, "class=%s ", opts->mailto_class); if (err) break; } err = string_append(out, "href=\"mailto:"); if (err) break; err = string_appendn (out, src + x, parts[i].end - x); if (err != STATUS_OK) break; err = string_append (out, "\">"); if (err != STATUS_OK) break; err = html_escape_alloc(src + x, parts[i].end - x, &esc); if (err != STATUS_OK) break; err = string_append (out, esc); free(esc); if (err != STATUS_OK) break; err = string_append (out, "</a>"); } x = parts[i].end; i++; } if (err != STATUS_OK) break; } free (parts); return err; }
static void writeUnlock(skipList list) { mUnlock(&list->write); return; }