int ssl_write(void *ssl, sstr * buf) { int i; SSL *s = (SSL *) ssl; i = SSL_write(s, sstr_buf(buf), sstr_len(buf)); return i; }
/* Escape non printable characters, and any characters from extras in the url * with the %xx equivalent. If % must be escaped then include it in extras. */ int urlescape(sstr * url, char *extras) { int i; sstr *tmp = sstr_init(0); for(i = 0; i < sstr_len(url); i++) { char c = sstr_getchar(url, i); if(strchr(extras, c) || !isprint(c)) { sstr_ncat(tmp, url, i); sstr_apprintf(tmp, "%%%x", c); sstr_split(url, NULL, 0, i + 1); i = -1; } } sstr_cat(tmp, url); sstr_cpy(url, tmp); sstr_free(tmp); return 0; }
int name2addr(sstr * str, struct in_addr *addr) { int c; c = sstr_getchar(str, 0); if (sstr_len(str) == 1 && c == '*') { addr->s_addr = INADDR_ANY; return (0); } if (c < '0' || c > '9') { struct hostent *hostinfo; hostinfo = gethostbyname(sstr_buf(str)); if (hostinfo == NULL) { fprintf(stderr, "Unable to resolve host %s\n", sstr_buf(str)); return (-1); } *addr = *((struct in_addr *) *hostinfo->h_addr_list); } else { if (inet_aton(sstr_buf(str), addr) == 0) return (-1); } return (0); }
/* ------------------------------------------------------------- ** ** Send command to server ** ------------------------------------------------------------- */ void send_command(sstr * cmd, sstr * arg) { sstr *buf; buf = sstr_init(MAX_LINE_LEN + 10); sstr_cat(buf, cmd); if(sstr_len(arg) != 0) { sstr_ncat2(buf, " ", 1); sstr_cat(buf, arg); } sstr_ncat2(buf, "\r\n", 2); #ifdef DEBUG fprintf(stderr, " C: \033[31m%s\033[37m", sstr_buf(buf)); #else write_log(VERBOSE, " C: %s", sstr_buf(buf)); #endif if(info->ssl_sc) ssl_write(info->ssl_sc, buf); else sstr_write(info->server_control.fd, buf, 0); sstr_free(buf); }
int set_opt(struct option_array *opt, sstr * str) { sstr *tok; int sep; if (rereading && !opt->reloadable) return (0); tok = sstr_init(0); sstr_ncat2(str, "\n", 1); /*For sstr_token */ opt->essential = FALSE; switch (opt->type) { case BOOL: sstr_token(str, tok, " \t\r\n", 0); if (!sstr_casecmp2(tok, "yes")) *(int *) opt->var = TRUE; else if (!sstr_casecmp2(tok, "no")) *(int *) opt->var = FALSE; else return (-1); break; case FILENAME: case STRING: sstr_token(str, tok, " \t\r\n", SSTR_QTOK); *(char **) opt->var = strdup(sstr_buf(tok)); break; case DIRECTRY: sstr_token(str, tok, " \t\r\n", SSTR_QTOK); if (sstr_getchar(tok, sstr_len(tok) - 1) != '/') sstr_ncat2(tok, "/", 1); *(char **) opt->var = strdup(sstr_buf(tok)); break; case ADDRESS: sstr_token(str, tok, " \t\r\n", 0); return name2addr(tok, (struct in_addr *) opt->var); break; case ADDRPRT: sep = sstr_token(str, tok, " :\t\r\n", 0); if( name2addr(tok, &((struct sockaddr_in *) opt->var)->sin_addr)==-1) return(-1); if (sep == ':') ((struct sockaddr_in *) opt->var)->sin_port = ntohs(sstr_atoi(str)); ((struct sockaddr_in *) opt->var)->sin_family = AF_INET; break; case INT: sstr_token(str, tok, " \t\r\n", 0); *(int *) opt->var = sstr_atoi(tok); break; case PRTRNGE: sstr_token(str, tok, " \t-,\r\n", 0); ((int *) opt->var)[0] = sstr_atoi(tok); ((int *) opt->var)[1] = sstr_atoi(str); if(!valid_uint16(((int *) opt->var)[0]) || !valid_uint16(((int *) opt->var)[1])) { fprintf(stderr, "Port out of range\n"); return -1; } if(((int *) opt->var)[0] >= ((int *) opt->var)[1]) { fprintf(stderr, "Port range is inverted\n"); return -1; } break; case ACL: return store_acl(str, (struct acl_list *) opt->var); break; case SUBSECT: return store_subsect(str, (struct subsect_list *) opt->var); } sstr_free(tok); return (0); }
static int _cmd_to_proto(char **target, const char *format, va_list ap) { const char *c = format; char *cmd = NULL; /* final command */ int pos; /* position in final command */ sstr curarg, newarg; int touched = 0; /* was the current argument touched? */ char **curargv = NULL, **newargv = NULL; int argc = 0; int totlen = 0; int j; /* Abort if there is not target to set */ if (target == NULL) return -1; /* Build the command string accordingly to protocol */ curarg = sstr_empty(); if (curarg == NULL) return -1; while(*c != '\0') { if (*c != '%' || c[1] == '\0') { if (*c == ' ') { if (touched) { newargv = realloc(curargv,sizeof(char*)*(argc+1)); if (newargv == NULL) goto err; curargv = newargv; curargv[argc++] = curarg; totlen += bulklen(sstr_len(curarg)); /* curarg is put in argv so it can be overwritten. */ curarg = sstr_empty(); if (curarg == NULL) goto err; touched = 0; } } else { newarg = sstr_catlen(curarg,c,1); if (newarg == NULL) goto err; curarg = newarg; touched = 1; } } else { char *arg; size_t size; /* Set newarg so it can be checked even if it is not touched. */ newarg = curarg; switch(c[1]) { case 's': arg = va_arg(ap,char*); size = strlen(arg); if (size > 0) newarg = sstr_catlen(curarg,arg,size); break; case 'b': arg = va_arg(ap,char*); size = va_arg(ap,size_t); if (size > 0) newarg = sstr_catlen(curarg,arg,size); break; case '%': newarg = sstr_cat(curarg,"%"); break; default: /* Try to detect printf format */ { static const char intfmts[] = "diouxX"; char _format[16]; const char *_p = c+1; size_t _l = 0; va_list _cpy; /* Flags */ if (*_p != '\0' && *_p == '#') _p++; if (*_p != '\0' && *_p == '0') _p++; if (*_p != '\0' && *_p == '-') _p++; if (*_p != '\0' && *_p == ' ') _p++; if (*_p != '\0' && *_p == '+') _p++; /* Field width */ while (*_p != '\0' && isdigit(*_p)) _p++; /* Precision */ if (*_p == '.') { _p++; while (*_p != '\0' && isdigit(*_p)) _p++; } /* Copy va_list before consuming with va_arg */ va_copy(_cpy,ap); /* Integer conversion (without modifiers) */ if (strchr(intfmts,*_p) != NULL) { va_arg(ap,int); goto fmt_valid; } /* Double conversion (without modifiers) */ if (strchr("eEfFgGaA",*_p) != NULL) { va_arg(ap,double); goto fmt_valid; } /* Size: char */ if (_p[0] == 'h' && _p[1] == 'h') { _p += 2; if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { va_arg(ap,int); /* char gets promoted to int */ goto fmt_valid; } goto fmt_invalid; } /* Size: short */ if (_p[0] == 'h') { _p += 1; if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { va_arg(ap,int); /* short gets promoted to int */ goto fmt_valid; } goto fmt_invalid; } /* Size: long long */ if (_p[0] == 'l' && _p[1] == 'l') { _p += 2; if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { va_arg(ap,long long); goto fmt_valid; } goto fmt_invalid; } /* Size: long */ if (_p[0] == 'l') { _p += 1; if (*_p != '\0' && strchr(intfmts,*_p) != NULL) { va_arg(ap,long); goto fmt_valid; } goto fmt_invalid; } fmt_invalid: va_end(_cpy); goto err; fmt_valid: _l = (_p+1)-c; if (_l < sizeof(_format)-2) { memcpy(_format,c,_l); _format[_l] = '\0'; newarg = sstr_catvprintf(curarg,_format,_cpy); /* Update current position (note: outer blocks * increment c twice so compensate here) */ c = _p-1; } va_end(_cpy); break; } } if (newarg == NULL) goto err; curarg = newarg; touched = 1; c++; } c++; } /* Add the last argument if needed */ if (touched) { newargv = realloc(curargv,sizeof(char*)*(argc+1)); if (newargv == NULL) goto err; curargv = newargv; curargv[argc++] = curarg; totlen += bulklen(sstr_len(curarg)); } else { sstr_free(curarg); } /* Clear curarg because it was put in curargv or was free'd. */ curarg = NULL; /* Add bytes needed to hold multi bulk count */ totlen += 1+intlen(argc)+2; /* Build the command at protocol level */ cmd = malloc(totlen+1); if (cmd == NULL) goto err; pos = sprintf(cmd,"*%d\r\n",argc); for (j = 0; j < argc; j++) { pos += sprintf(cmd+pos,"$%zu\r\n",sstr_len(curargv[j])); memcpy(cmd+pos,curargv[j],sstr_len(curargv[j])); pos += sstr_len(curargv[j]); sstr_free(curargv[j]); cmd[pos++] = '\r'; cmd[pos++] = '\n'; } assert(pos == totlen); cmd[pos] = '\0'; free(curargv); *target = cmd; return totlen; err: while(argc--) sstr_free(curargv[argc]); free(curargv); if (curarg != NULL) sstr_free(curarg); /* No need to check cmd since it is the last statement that can fail, * but do it anyway to be as defensive as possible. */ if (cmd != NULL) free(cmd); return -1; }