+/* --- @tx_configure@ --- *
+ *
+ * Arguments: @txport *tx@ = pointer to transport block
+ * @const char *config@ = config string
+ *
+ * Returns: Zero if OK, nonzero on errors.
+ *
+ * Use: Applies a configuration string to a transport.
+ */
+
+int tx_configure(txport *tx, const char *config)
+{
+ char *c;
+ char *k, *v;
+ int rc = -1;
+
+ if (!config)
+ return (0);
+ c = xstrdup(config);
+ for (k = strtok(c, ";"); k; k = strtok(0, ";")) {
+ if ((v = strchr(k, '=')) != 0)
+ *v++ = 0;
+ if (strcmp(k, "nl") == 0 || strcmp(k, "newline") == 0) {
+ int d;
+ if (!v)
+ d = LBUF_CRLF;
+ else if (strcmp(v, "none") == 0)
+ d = 0;
+ else if (strcmp(v, "crlf") == 0)
+ d = LBUF_CRLF;
+ else if (strcmp(v, "crlf-strict") == 0 ||
+ strcmp(v, "strict-crlf") == 0)
+ d = LBUF_STRICTCRLF;
+ else if (strcmp(v, "cr") == 0)
+ d = '\r';
+ else if (strcmp(v, "lf") == 0)
+ d = '\n';
+ else if (v[0] == '\\') switch (v[1]) {
+ case 0: d = '\\'; break;
+ case 'a': d = 0x07; goto d_single;
+ case 'b': d = 0x08; goto d_single;
+ case 'f': d = 0x0c; goto d_single;
+ case 'n': d = 0x0a; goto d_single;
+ case 'r': d = 0x0d; goto d_single;
+ case 't': d = 0x09; goto d_single;
+ case 'v': d = 0x0b; goto d_single;
+ case 'e': d = 0x1b; goto d_single;
+ case 'x':
+ if (!isxdigit((unsigned char)v[2]) ||
+ (d = strtoul(v + 2, &v, 16) || *v)) {
+ err_report(ERR_TXPORT, ERRTX_CONFIG, 0,
+ "bad hex escape `%s' in `newline' config", v);
+ goto err;
+ }
+ break;
+ default:
+ if (isdigit((unsigned char)v[0])) {
+ d = strtoul(v + 1, &v, 8);
+ if (*v) {
+ err_report(ERR_TXPORT, ERRTX_CONFIG, 0,
+ "bad octal escape `%s' in `newline' config", v);
+ goto err;
+ }
+ }
+ d = v[1];
+ d_single:
+ if (v[2]) {
+ err_report(ERR_TXPORT, ERRTX_CONFIG, 0,
+ "unknown escape `%s' in `newline' config", v);
+ goto err;
+ }
+ break;
+ } else if (v[1] == 0)
+ d = v[0];
+ else {
+ err_report(ERR_TXPORT, ERRTX_CONFIG, 0,
+ "unknown delimiter `%s' in `newline' config", v);
+ goto err;
+ }
+ tx->lb.delim = d;
+ } else {
+ int e = 0;
+ if (tx->ops->configure)
+ e = tx->ops->configure(tx, k, v);
+ if (!e) {
+ err_report(ERR_TXPORT, ERRTX_CONFIG, 0,
+ "unrecognized configuration keyword `%s'", k);
+ }
+ if (e <= 0)
+ goto err;
+ }
+ }
+
+ rc = 0;
+err:
+ xfree(c);
+ return (rc);
+}
+