/*--------------------------------------------------------------------*/ string_t * intersect_strings (const string_t * p_left, const string_t * p_right, Bool bSubtract) /* !bSubtract: Intersect string <left> with string <right> and return * a newly allocated string with all those characters which are in * both strings. * bSubtract: Subtract string <right> from string <left> and return * a newly allocated string with all those characters which are in * <left> but not in <right>. * The order of the characters returned is their order of appearance * in <left>. */ { size_t len_left, len_right, len_out; size_t ix_left, ix_right; long * pos; CBool * matches; const char * left_txt; char * left, * right, * result_txt; string_t *result; len_left = mstrsize(p_left); len_right = mstrsize(p_right); xallocate(matches, len_left+1, "intersection matches"); /* +1 so that smalloc won't complain when given an empty left string */ for (ix_left = 0; ix_left < len_left; ix_left++) matches[ix_left] = bSubtract ? MY_TRUE : MY_FALSE; /* Sort the two strings */ left = sort_string(p_left, len_left, &pos); right = sort_string(p_right, len_right, NULL); /* Intersect the two strings by mutual comparison. * Each non-matched character in left gets is pos[] set to -1. */ len_out = bSubtract ? len_left : 0; for ( ix_left = 0, ix_right = 0 ; ix_left < len_left && ix_right < len_right ; ) { if (left[ix_left] < right[ix_right]) ix_left++; else if (left[ix_left] > right[ix_right]) ix_right++; else /* left[ix_left] == right[ix_right]) */ { if (!bSubtract) { matches[pos[ix_left]] = MY_TRUE; len_out++; } else { matches[pos[ix_left]] = MY_FALSE; len_out--; } ix_left++; } } /* Create the result: copy all flagged characters */ memsafe(result = alloc_mstring(len_out), len_out, "intersection result"); left_txt = get_txt((string_t *const)p_left); result_txt = get_txt(result); for (ix_left = 0, ix_right = 0; ix_left < len_left; ix_left++) if (matches[ix_left]) result_txt[ix_right++] = left_txt[ix_left]; /* Free intermediate results */ xfree(pos); xfree(matches); xfree(left); xfree(right); return result; } /* intersect_strings() */
/*-------------------------------------------------------------------------*/ int tls_continue_handshake (interactive_t *ip) /* Continue the TLS initialisation handshake for interactive <ip>. * Return a negative error code if the connection can not be set up. * Return 0 if the connection is still begin set up. * Return 1 if the connection is now active (or if no secure connection * had been requested). * * If a callback is set for <ip> and connection comes out of the handshaking * state, it will be called with the result code. */ { int ret; if (ip->tls_status != TLS_HANDSHAKING) return 1; ret = tls_do_handshake(ip); if (!ret) return 0; if (ret < 0) { ip->tls_status = TLS_INACTIVE; } else { ip->tls_status = TLS_ACTIVE; } /* If the connection is no longer in handshake, execute the callback */ if (ip->tls_cb != NULL) { tls_cb_handler_t * handler; xallocate( handler, sizeof(*handler) , "TLS: Callback handler protector"); handler->cb = ip->tls_cb; ip->tls_cb = NULL; /* Protect the callback during its execution. */ push_error_handler (handle_tls_cb_error, &(handler->head)); push_number(inter_sp, ret < 0 ? ret : 0); push_ref_object(inter_sp, ip->ob, "tls_handshake"); command_giver = ip->ob; current_interactive = ip->ob; /* Set current_interactive as it would be for a normal logon() call. */ (void)apply_callback(handler->cb, 2); if (!(ip->ob->flags & O_DESTRUCTED)) print_prompt(); command_giver = NULL; free_svalue(inter_sp); inter_sp--; /* free the callback */ } return ret; } /* tls_continue_handshake() */
svalue_t * f_convert_charset (svalue_t *sp) /* EFUN convert_charset() * * string convert_charset(string str, string from_cs, string to_cs) * * Convert the string <str> from charset <from_cs> to charset <to_cs> * and return the converted string. * * The efun is only available on systems with libiconv. */ { iconv_t context; string_t *from_cs, *to_cs, *in_str, *out_str; #if HAS_ICONV_NONCONST_IN # define ICONV_IN_CAST (char**) #else # define ICONV_IN_CAST #endif const char *pIn; /* Input string pointer */ size_t in_len; /* Input length */ size_t in_left; /* Input length left */ char * out_buf; /* Output buffer */ size_t out_size; /* Size of the output buffer */ size_t out_left; /* Size left in output buffer */ char *pOut; /* Output string pointer */ in_str = sp[-2].u.str; from_cs = sp[-1].u.str; to_cs = sp->u.str; pIn = get_txt(in_str); in_len = mstrsize(in_str); in_left = in_len; /* If the input string is empty, we can return immediately * (and in fact must since the allocator will balk at allocating 0 bytes) */ if (!in_len) { sp -= 2; free_string_svalue(sp); free_string_svalue(sp+1); put_string(sp, sp[2].u.str); return sp; } /* Allocate a temporary output string */ out_size = in_len > 65536 ? (in_len + 33) : (2 * in_len); out_left = out_size; xallocate(out_buf, out_size, "iconv buffer"); pOut = out_buf; /* Open the iconv context */ context = iconv_open(get_txt(to_cs), get_txt(from_cs)); if (context == (iconv_t) -1) { xfree(out_buf); if (errno == EINVAL) errorf("convert_charset(): Conversion '%s' -> '%s' not supported.\n" , get_txt(from_cs), get_txt(to_cs) ); else errorf("convert_charset(): Error %d.\n", errno); /* NOTREACHED */ return sp; } /* Convert the string, reallocating the output buffer where necessary */ while (in_left) { size_t rc; rc = iconv(context, ICONV_IN_CAST &pIn, &in_left, &pOut, &out_left); if (rc == (size_t)-1) { if (errno == E2BIG) { /* Reallocate output buffer */ size_t newsize; char * tmp; newsize = out_size + (in_len > 128 ? in_len : 128); tmp = rexalloc(out_buf, newsize); if (!tmp) { iconv_close(context); xfree(out_buf); outofmem(newsize, "iconv buffer"); /* NOTREACHED */ return sp; } out_buf = tmp; pOut = out_buf + out_size; out_left = newsize - out_size; out_size = newsize; continue; } /* Other error: clean up */ iconv_close(context); xfree(out_buf); if (errno == EILSEQ) { errorf("convert_charset(): Invalid character sequence at " "index %td\n", (ptrdiff_t)(pIn - get_txt(in_str))); /* NOTREACHED */ return sp; } if (errno == EINVAL) { errorf("convert_charset(): Incomplete character sequence at " "index %td\n", (ptrdiff_t)(pIn - get_txt(in_str))); /* NOTREACHED */ return sp; } errorf("convert_charset(): Error %d at index %td\n" , errno, (ptrdiff_t)(pIn - get_txt(in_str)) ); /* NOTREACHED */ return sp; } /* if (rc < 0) */ } /* while (in_left) */ /* While the actual conversion is complete, the output stream may now * be in a non-base state. Add the necessary epilogue to get back * to the base state. */ while(1) { size_t rc; rc = iconv(context, NULL, NULL, &pOut, &out_left); if (rc == (size_t)-1) { if (errno == E2BIG) { /* Reallocate output buffer */ size_t newsize; char * tmp; newsize = out_size + (in_len > 128 ? in_len : 128); tmp = rexalloc(out_buf, newsize); if (!tmp) { iconv_close(context); xfree(out_buf); outofmem(newsize, "iconv buffer"); /* NOTREACHED */ return sp; } out_buf = tmp; pOut = out_buf + out_size; out_left = newsize - out_size; out_size = newsize; continue; } /* Other error: clean up */ iconv_close(context); xfree(out_buf); if (errno == EILSEQ) { errorf("convert_charset(): Invalid character sequence at " "index %td\n", (ptrdiff_t)(pIn - get_txt(in_str))); /* NOTREACHED */ return sp; } if (errno == EINVAL) { errorf("convert_charset(): Incomplete character sequence at " "index %td\n", (ptrdiff_t)(pIn - get_txt(in_str))); /* NOTREACHED */ return sp; } errorf("convert_charset(): Error %d at index %td\n" , errno, (ptrdiff_t)(pIn - get_txt(in_str)) ); /* NOTREACHED */ return sp; } /* if (rc < 0) */ /* At this point, the iconv() succeeded: we're done */ break; } /* while(1) */ iconv_close(context); /* Get the return string and prepare the return arguments */ out_str = new_n_mstring(out_buf, out_size - out_left); xfree(out_buf); if (!out_str) { outofmem(out_size - out_left, "convert_charset() result"); /* NOTREACHED */ return sp; } free_string_svalue(sp--); free_string_svalue(sp--); free_string_svalue(sp); put_string(sp, out_str); return sp; } /* f_convert_charset() */