void buffer_vprintf(buffer *b, const char *format, va_list ap) { char c; const char *s; buffer *buf; while (*format) { if (*format == '%') { format++; switch (*format) { case 'c': c = va_arg(ap, int); buffer_append_char(b, c); break; case 's': s = va_arg(ap, const char *); buffer_append_str(b, s); break; case 'b': buf = va_arg(ap, buffer *); buffer_append_buffer(b, buf); break; default: buffer_append_char(b, '%'); break; } } else
static void report( neko_vm *vm, value exc, int isexc ) { int i; buffer b = alloc_buffer(NULL); value st = neko_exc_stack(vm); for(i=0;i<val_array_size(st);i++) { value s = val_array_ptr(st)[i]; buffer_append(b,"Called from "); if( val_is_null(s) ) buffer_append(b,"a C function"); else if( val_is_string(s) ) { buffer_append(b,val_string(s)); buffer_append(b," (no debug available)"); } else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) ) { val_buffer(b,val_array_ptr(s)[0]); buffer_append(b," line "); val_buffer(b,val_array_ptr(s)[1]); } else val_buffer(b,s); buffer_append_char(b,'\n'); } if( isexc ) buffer_append(b,"Uncaught exception - "); val_buffer(b,exc); # ifdef NEKO_STANDALONE neko_standalone_error(val_string(buffer_to_string(b))); # else fprintf(stderr,"%s\n",val_string(buffer_to_string(b))); # endif }
void buffer_append_str(buffer *b, const char *s) { if (!s) return; while (*s) buffer_append_char(b, *s++); }
TEST(Buffer, Append) { char * text; buffer * buf; buf = buffer_new(8); buffer_prepare(buf, 2); EXPECT_EQ(buf->size, 8); buffer_prepare(buf, 10); EXPECT_EQ(buf->size, 18); buffer_append_string(buf, "Hello"); EXPECT_EQ(buf->used, 5); buffer_append_char(buf, ' '); EXPECT_TRUE(strncmp((char*)buf->data, "Hello ", buf->used) == 0); text = strdup("WORLD"); buffer_append_data_tolower(buf, (unsigned char*) text, strlen(text)); EXPECT_TRUE(strncmp((char*)buf->data, "Hello world", buf->used) == 0); free(text); text = strdup("\nWORLD\n..."); buffer_append_string_n(buf, text, 6); EXPECT_TRUE(strncmp((char*)buf->data, "Hello world\nWORLD", buf->used) == 0); free(text); buffer_destroy(buf); }
/** buffer_add_char : 'buffer -> c:int -> void <doc>Add a single char to a buffer. Error if [c] is not in the 0..255 range</doc> **/ static value buffer_add_char( value b, value c ) { val_check_kind(b,k_buffer); val_check(c,int); if( val_int(c) < 0 || val_int(c) > 255 ) neko_error(); buffer_append_char( (buffer)val_data(b), (char)(unsigned char)val_int(c) ); return val_true; }
void buffer_append_buffer(buffer *b, buffer *x) { int c; buffer_iterator it; buffer_get_iterator(x, &it); while((c = buffer_iterator_next(&it)) != EOF) buffer_append_char(b, c); }
/** request : 'db -> sql:string -> 'result <doc>Executes the SQL request and returns its result</doc> **/ static value request( value v, value sql ) { database *db; result *r; const char *tl; int i,j; val_check_kind(v,k_db); val_check(sql,string); db = val_db(v); r = (result*)alloc(sizeof(result)); r->db = db; if( sqlite3_prepare(db->db,val_string(sql),val_strlen(sql),&r->r,&tl) != SQLITE_OK ) { buffer b = alloc_buffer("Sqlite error in "); val_buffer(b,sql); buffer_append(b," : "); buffer_append(b,sqlite3_errmsg(db->db)); val_throw(buffer_to_string(b)); } if( *tl ) { sqlite3_finalize(r->r); val_throw(alloc_string("Cannot execute several SQL requests at the same time")); } r->ncols = sqlite3_column_count(r->r); r->names = (field*)alloc_private(sizeof(field)*r->ncols); r->bools = (int*)alloc_private(sizeof(int)*r->ncols); r->first = 1; r->done = 0; for(i=0;i<r->ncols;i++) { field id = val_id(sqlite3_column_name(r->r,i)); const char *dtype = sqlite3_column_decltype(r->r,i); for(j=0;j<i;j++) if( r->names[j] == id ) { if( strcmp(sqlite3_column_name(r->r,i),sqlite3_column_name(r->r,j)) == 0 ) { buffer b = alloc_buffer("Error, same field is two times in the request "); val_buffer(b,sql); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } else { buffer b = alloc_buffer("Error, same field ids for : "); buffer_append(b,sqlite3_column_name(r->r,i)); buffer_append(b," and "); buffer_append(b,sqlite3_column_name(r->r,j)); buffer_append_char(b,'.'); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } } r->names[i] = id; r->bools[i] = dtype?(strcmp(dtype,"BOOL") == 0):0; } // changes in an update/delete if( db->last != NULL ) finalize_result(val_result(db->last),0); db->last = alloc_abstract(k_result,r); return db->last; }
static void zlib_error( z_stream *z, int err ) { buffer b = alloc_buffer("ZLib Error : "); if( z && z->msg ) { buffer_append(b,z->msg); buffer_append(b," ("); } val_buffer(b,alloc_int(err)); if( z && z->msg ) buffer_append_char(b,')'); val_throw(buffer_to_string(b)); }
int buffer_stream_putchar(char c, FILE *f) { buffer_stream_t *pbs; pbs = fdev_get_udata(f); buffer_append_char(pbs->pbufout, c); if( pbs->outcb != NULL) { pbs->outcb(pbs->pbufout); } return EOF; }
TEST(Buffer, Case) { buffer * buf; buf = buffer_new(1); buffer_append_char(buf, 'n'); EXPECT_EQ(buf->used, 1); EXPECT_EQ(buf->size, 1); buffer_append_string(buf, "Idium-a-nEw-breed-of-browser"); EXPECT_EQ(buf->used, 29); buffer_camelify(buf); EXPECT_TRUE(strncmp((char*)buf->data, "NIdium-A-NEw-Breed-Of-Browser ", buf->used) == 0); //@FIXME: EXPECT_TRUE(strncmp((char*)buf->data, "NidiumANewBreedOfBrowser ", buf->used) == 0); EXPECT_EQ(buf->used, 24); buffer_destroy(buf); }
static int read_http_header(buffer *header, pool_t *p, int fd){ int palloc_size = 1024; char *c ; char *ptr; c = palloc(p,sizeof(char)); header->ptr = palloc(p, palloc_size); header->size = palloc_size; while(read(fd, c, 1)) { buffer_append_char(header,*c,p); if(*c == '\n' && header->used >= 2) { ptr = header->ptr + header->used - 2; if(strncasecmp(ptr, "\n\n", 2) == 0) { return 0; } } } return 0; }
/** * A subparser function for compiler_build() that looks at the current token, * checks for a 'function' token. If found, it proceeds to evaluate the function * declaration, make note of the number of arguments, and store the index where * the function will begin in the byte code. This function then dispatches * subparsers that define stack variables, evaluate logical blocks (if, else, * while, etc), and evaluate straight code. * c: an instance of Compiler. * l: an instance of lexer. * returns: false if the current token is not the start of a function declaration * ('function'), and true if it is. If an error occurs, function returns true, * but c->err is set to a relevant error code. */ static bool parse_function_definitions(Compiler * c, Lexer * l) { /* * A Function definition looks like so: * * function [EXPORTED] [NAME] ( [ARG1], [ARG2], ... ) { * [code] * } * * The code below parses these tokens and then dispatches the straight code * parsers to handle the function body. */ bool exported = false; size_t len; LexerType type; char * token = lexer_current_token(l, &type, &len); char * name; size_t nameLen; int numArgs; int numVars; /* check that this is a function declaration token */ if(!tokens_equal(token, len, LANG_FUNCTION, LANG_FUNCTION_LEN)) { c->err = COMPILERERR_UNEXPECTED_TOKEN; return false; } /* advance to next token. if is is EXPORTED, take note for later */ token = lexer_next(l, &type, &len); if(tokens_equal(token, len, LANG_EXPORTED, LANG_EXPORTED_LEN)) { exported = true; token = lexer_next(l, &type, &len); } /* this is the name token, store it and check for correct type */ name = token; nameLen = len; if(type != LEXERTYPE_KEYVAR || is_keyword(name, nameLen)) { c->err = COMPILERERR_EXPECTED_FNAME; return true; } /* check if name is too long */ if(nameLen > GS_MAX_FUNCTION_NAME_LEN) { c->err = COMPILERERR_FUNCTION_NAME_TOO_LONG; return true; } /* check for the open parenthesis */ token = lexer_next(l, &type, &len); if(!tokens_equal(token, len, LANG_OPARENTH, LANG_OPARENTH_LEN)) { c->err = COMPILERERR_EXPECTED_OPARENTH; return true; } /* we're going down a level. push new symbol table to stack */ if(!symtblstk_push(c)) { c->err = COMPILERERR_ALLOC_FAILED; return true; } /* parse the arguments, return if the process fails */ if((numArgs = parse_arguments(c, l)) == -1) { return true; } /* check for open brace defining start of function "{" */ token = lexer_next(l, &type, &len); if(!tokens_equal(token, len, LANG_OBRACKET, LANG_OBRACKET_LEN)) { c->err = COMPILERERR_EXPECTED_OBRACKET; return true; } token = lexer_next(l, &type, &len); /****************************** Do function body ****************************/ /* handle variable declarations */ if((numVars = define_variables(c, l)) == -1) { return false; } /* retrieve next token (it was modified by define_variable */ token = lexer_current_token(l, &type, &len); /* store the function name, location in the output, and # of args and vars */ if(!function_store_definition(c, name, nameLen, numArgs, numVars, exported)) { return true; } if(!parse_body(c, l)) { return true; } /* retrieve current token (it was modified by parse_body) */ token = lexer_current_token(l, &type, &len); /****************************** End function body ***************************/ /* check for closing brace defining end of body "}" */ if(!tokens_equal(token, len, LANG_CBRACKET, LANG_CBRACKET_LEN)) { c->err = COMPILERERR_EXPECTED_CBRACKET; return true; } /* push default return value. if no other return is given, this value is * returned */ buffer_append_char(vm_buffer(c->vm), OP_NULL_PUSH); /* pop function frame and return to calling function */ buffer_append_char(vm_buffer(c->vm), OP_FRM_POP); token = lexer_next(l, &type, &len); /* we're done here! pop the symbol table for this function off the stack. */ ht_free(symtblstk_pop(c)); return true; }
/** process_run : cmd:string -> args:string array -> 'process <doc> Start a process using a command and the specified arguments. When args is not null, cmd and args will be auto-quoted/escaped. If no auto-quoting/escaping is desired, you should append necessary arguments to cmd as if it is inputted to the shell directly, and pass null as args. </doc> **/ static value process_run( value cmd, value vargs ) { int i, isRaw; vprocess *p; val_check(cmd,string); isRaw = val_is_null(vargs); if (!isRaw) { val_check(vargs,array); } # ifdef NEKO_WINDOWS { SECURITY_ATTRIBUTES sattr; STARTUPINFO sinf; HANDLE proc = GetCurrentProcess(); HANDLE oread,eread,iwrite; // creates commandline buffer b = alloc_buffer(NULL); value sargs; if (isRaw) { char* cmdexe = getenv("COMSPEC"); if (!cmdexe) cmdexe = "cmd.exe"; buffer_append(b,"\""); buffer_append(b,cmdexe); buffer_append(b,"\" /C \""); buffer_append(b,val_string(cmd)); buffer_append_char(b,'"'); } else { buffer_append_char(b,'"'); val_buffer(b,cmd); buffer_append_char(b,'"'); for(i=0;i<val_array_size(vargs);i++) { value v = val_array_ptr(vargs)[i]; int j,len; unsigned int bs_count = 0; unsigned int k; val_check(v,string); len = val_strlen(v); buffer_append(b," \""); for(j=0;j<len;j++) { char c = val_string(v)[j]; switch( c ) { case '"': // Double backslashes. for (k=0;k<bs_count*2;k++) { buffer_append_char(b,'\\'); } bs_count = 0; buffer_append(b, "\\\""); break; case '\\': // Don't know if we need to double yet. bs_count++; break; default: // Normal char for (k=0;k<bs_count;k++) { buffer_append_char(b,'\\'); } bs_count = 0; buffer_append_char(b,c); break; } } // Add remaining backslashes, if any. for (k=0;k<bs_count*2;k++) { buffer_append_char(b,'\\'); } buffer_append_char(b,'"'); } } sargs = buffer_to_string(b); p = (vprocess*)alloc_private(sizeof(vprocess)); // startup process sattr.nLength = sizeof(sattr); sattr.bInheritHandle = TRUE; sattr.lpSecurityDescriptor = NULL; memset(&sinf,0,sizeof(sinf)); sinf.cb = sizeof(sinf); sinf.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; sinf.wShowWindow = SW_HIDE; CreatePipe(&oread,&sinf.hStdOutput,&sattr,0); CreatePipe(&eread,&sinf.hStdError,&sattr,0); CreatePipe(&sinf.hStdInput,&iwrite,&sattr,0); DuplicateHandle(proc,oread,proc,&p->oread,0,FALSE,DUPLICATE_SAME_ACCESS); DuplicateHandle(proc,eread,proc,&p->eread,0,FALSE,DUPLICATE_SAME_ACCESS); DuplicateHandle(proc,iwrite,proc,&p->iwrite,0,FALSE,DUPLICATE_SAME_ACCESS); CloseHandle(oread); CloseHandle(eread); CloseHandle(iwrite); if( !CreateProcess(NULL,val_string(sargs),NULL,NULL,TRUE,0,NULL,NULL,&sinf,&p->pinf) ) neko_error(); // close unused pipes CloseHandle(sinf.hStdOutput); CloseHandle(sinf.hStdError); CloseHandle(sinf.hStdInput); } # else char **argv; if (isRaw) { argv = (char**)alloc_private(sizeof(char*)*4); argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = val_string(cmd); argv[3] = NULL; } else { argv = (char**)alloc_private(sizeof(char*)*(val_array_size(vargs)+2)); argv[0] = val_string(cmd); for(i=0;i<val_array_size(vargs);i++) { value v = val_array_ptr(vargs)[i]; val_check(v,string); argv[i+1] = val_string(v); } argv[i+1] = NULL; } int input[2], output[2], error[2]; if( pipe(input) || pipe(output) || pipe(error) ) neko_error(); p = (vprocess*)alloc_private(sizeof(vprocess)); p->pid = fork(); if( p->pid == -1 ) { do_close(input[0]); do_close(input[1]); do_close(output[0]); do_close(output[1]); do_close(error[0]); do_close(error[1]); neko_error(); } // child if( p->pid == 0 ) { close(input[1]); close(output[0]); close(error[0]); dup2(input[0],0); dup2(output[1],1); dup2(error[1],2); execvp(argv[0],argv); fprintf(stderr,"Command not found : %s\n",val_string(cmd)); exit(1); } // parent do_close(input[0]); do_close(output[1]); do_close(error[1]); p->iwrite = input[1]; p->oread = output[0]; p->eread = error[0]; # endif { value vp = alloc_abstract(k_process,p); val_gc(vp,free_process); return vp; } }
enum json_error json_parser_scan_whitespace(const char** in, const char* end, struct whitespace* out) { assert(*in < end); struct buffer buffer = { .content = NULL, .length = 0, .size = 0 }; while(*in < end) { if(**in != 0x20 && **in != 0x09 && **in != 0x0A && **in != 0x0D) { break; } if(out) buffer_append(&buffer, *in, 1); (*in)++; } if(buffer.length != 0) { out->content = buffer.content; out->length = buffer.length; } return JSON_ERROR_OK; } enum json_error json_parser_scan_object(const char** in, const char* end, struct json_object* out) { assert(*in < end); if(**in != '{') return JSON_ERROR_OK; (*in)++; struct json_string* keys = NULL; struct json_value* values = NULL; unsigned int size = 0, length = 0; // struct whitespace* whitespaces = NULL; // unsigned int whitespaces_size = 0, whitespaces_length = 0; enum json_error error; const char* tmp_pos; struct whitespace whitespace = { .length = 0 }; while(*in < end) { json_parser_scan_whitespace(in, end, &whitespace); // if(whitespace.length) { // whitespace.length = 0; // } if(*in >= end) goto unexpected_end; struct json_string key; tmp_pos = *in; error = json_parser_scan_string(in, end, &key); if(error) goto error; if(*in == tmp_pos) break; if(*in >= end) goto unexpected_end; json_parser_scan_whitespace(in, end, &whitespace); // if(whitespace.length) { // whitespace.length = 0; // } if(*in >= end) goto unexpected_end; if(**in != ':') { error = JSON_ERROR_UNEXPECTED_TOKEN; goto error; } (*in)++; if(*in >= end) goto unexpected_end; json_parser_scan_whitespace(in, end, &whitespace); // if(whitespace.length) { // whitespace.length = 0; // } if(*in >= end) goto unexpected_end; struct json_value value; tmp_pos = *in; error = json_parser_scan_value(in, end, &value); if(error) goto error; if(*in == tmp_pos) { error = JSON_ERROR_UNEXPECTED_TOKEN; goto error; } if(size < length + 1) { if(size == 0) { size = 1; keys = malloc(sizeof(struct json_string)); values = malloc(sizeof(struct json_value)); } else { size *= 2; keys = realloc(keys, sizeof(struct json_string) * size); values = realloc(values, sizeof(struct json_value) * size); } } keys[length] = key; values[length] = value; length++; if(*in >= end) goto unexpected_end; tmp_pos = *in; json_parser_scan_whitespace(in, end, &whitespace); // if(whitespace.length) { // whitespace.length = 0; // } if(*in >= end) goto unexpected_end; if(**in != ',') break; (*in)++; } if(*in >= end) goto unexpected_end; if(**in != '}') { error = JSON_ERROR_UNEXPECTED_TOKEN; goto error; } (*in)++; out->keys = keys; out->values = values; out->length = length; // out->whitespaces = whitespaces; // out->whitespaces_length = whitespaces_length; return JSON_ERROR_OK; unexpected_end: error = JSON_ERROR_UNEXPECTED_END; error: free(keys); free(values); // free(whitespaces); return error; } enum json_error json_parser_scan_array(const char** in, const char* end, struct json_array* out) { assert(*in < end); if(**in != '[') return JSON_ERROR_OK; (*in)++; struct json_value* values = NULL; unsigned int size = 0, length = 0; // struct whitespace* whitespaces = NULL; // unsigned int whitespaces_size = 0, whitespaces_length = 0; enum json_error error; const char* tmp_pos; struct whitespace whitespace = { .length = 0 }; while(*in < end) { json_parser_scan_whitespace(in, end, &whitespace); // if(whitespace.length) { // whitespace.length = 0; // } if(*in >= end) goto unexpected_end; struct json_value value; tmp_pos = *in; error = json_parser_scan_value(in, end, &value); if(error) goto error; if(*in == tmp_pos) { if(length == 0) break; error = JSON_ERROR_UNEXPECTED_TOKEN; goto error; } if(size < length + 1) { if(size == 0) { size = 1; values = malloc(sizeof(struct json_value)); } else { size *= 2; values = realloc(values, sizeof(struct json_value) * size); } } values[length] = value; length++; if(*in >= end) goto unexpected_end; tmp_pos = *in; json_parser_scan_whitespace(in, end, &whitespace); // if(whitespace.length) { // whitespace.length = 0; // } if(*in >= end) goto unexpected_end; if(**in != ',') break; (*in)++; } if(*in >= end) goto unexpected_end; if(**in != ']') { error = JSON_ERROR_UNEXPECTED_TOKEN; goto error; } (*in)++; out->values = values; out->length = length; // out->whitespaces = whitespaces; // out->whitespaces_length = whitespaces_length; return JSON_ERROR_OK; unexpected_end: error = JSON_ERROR_UNEXPECTED_END; error: free(values); // free(whitespaces); return error; } enum json_error json_parser_scan_string(const char** in, const char* end, struct json_string* out) { assert(*in < end); if(**in != '"') return JSON_ERROR_OK; struct buffer buffer = { .content = NULL, .length = 0, .size = 0 }; enum json_error error = 0; (*in)++; while(*in < end) { unsigned char c = **in; if(c == '"') break; if(c != '\\') { if(c <= 0x1f || c == 0x7f) { // disable control characters error = JSON_ERROR_UNEXPECTED_TOKEN; goto error; } buffer_append(&buffer, &c, 1); } else { (*in)++; if(*in >= end) goto unexpected_end; // early declaration uint16_t unicode_char; const char* uend = *in + 5; switch(**in) { default: error = JSON_ERROR_UNEXPECTED_TOKEN; goto error; case '"': case '\\': case '/': c = **in; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'u': if(uend > end) goto unexpected_end; (*in)++; unicode_char = 0; while(1) { unsigned char c; if(**in >= '0' && **in <= '9') c= **in - '0'; else if(**in >= 'a' && **in <= 'f') c = **in - 'a' + 10; else if(**in >= 'A' && **in <= 'F') c = **in - 'A' + 10; else { error = JSON_ERROR_UNEXPECTED_TOKEN; goto error; } unicode_char |= c; (*in)++; if(*in >= uend) break; unicode_char <<= 4; } // printf("Unicode in: %x\n", unicode_char); // FIXME: I guess this could be optimized/cleaned if(unicode_char < 0x80) { // printf("Bytes: %x\n", unicode_char); buffer_append_char(&buffer, (unicode_char & 0xff)); } else if(unicode_char < 0x800) { unsigned char firstByte = 0xc0 | (0x1f & (unicode_char >> 6)); unsigned char secondByte = 0x80 | (0x3f & unicode_char); // printf("Bytes: %x %x\n", firstByte, secondByte); buffer_append_char(&buffer, firstByte); buffer_append_char(&buffer, secondByte); } else { unsigned char firstByte = 0xe0 | (0x1f & (unicode_char >> 12)); unsigned char secondByte = 0x80 | (0x3f & (unicode_char >> 6)); unsigned char thirdByte = 0x80 | (0x3f & unicode_char); // printf("Bytes: %x %x %x\n", firstByte, secondByte, thirdByte); buffer_append_char(&buffer, firstByte); buffer_append_char(&buffer, secondByte); buffer_append_char(&buffer, thirdByte); } continue; } buffer_append(&buffer, &c, 1); } (*in)++; }
/** process_run_raw : cmd:string -> 'process <doc> Start a process using a command. The input string contains the command as well as the arguments. Shell meta-characters will not be auto escaped/quoted. </doc> **/ CAMLprim value process_run_raw( value cmd ) { int i; vprocess *p; val_check(cmd,string); char* cmdStr = val_string(cmd); # ifdef _WIN32 { SECURITY_ATTRIBUTES sattr; STARTUPINFO sinf; HANDLE proc = GetCurrentProcess(); HANDLE oread,eread,iwrite; // creates commandline buffer b = alloc_buffer(NULL); char *sargs; buffer_append_char(b,'"'); char* cmdexe = getenv("COMSPEC"); if (!cmdexe) cmdexe = "cmd.exe"; buffer_append_str(b,cmdexe); buffer_append_char(b,'"'); buffer_append_str(b,"/C \""); buffer_append_str(b,cmdStr); buffer_append_char(b,'"'); sargs = buffer_to_string(b); p = (vprocess*)alloc_private(sizeof(vprocess)); // startup process sattr.nLength = sizeof(sattr); sattr.bInheritHandle = TRUE; sattr.lpSecurityDescriptor = NULL; memset(&sinf,0,sizeof(sinf)); sinf.cb = sizeof(sinf); sinf.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; sinf.wShowWindow = SW_HIDE; CreatePipe(&oread,&sinf.hStdOutput,&sattr,0); CreatePipe(&eread,&sinf.hStdError,&sattr,0); CreatePipe(&sinf.hStdInput,&iwrite,&sattr,0); DuplicateHandle(proc,oread,proc,&p->oread,0,FALSE,DUPLICATE_SAME_ACCESS); DuplicateHandle(proc,eread,proc,&p->eread,0,FALSE,DUPLICATE_SAME_ACCESS); DuplicateHandle(proc,iwrite,proc,&p->iwrite,0,FALSE,DUPLICATE_SAME_ACCESS); CloseHandle(oread); CloseHandle(eread); CloseHandle(iwrite); if( !CreateProcess(NULL,val_string(sargs),NULL,NULL,TRUE,0,NULL,NULL,&sinf,&p->pinf) ) { CloseHandle(p->eread); CloseHandle(p->oread); CloseHandle(p->iwrite); free(sargs); neko_error(); } free(sargs); // close unused pipes CloseHandle(sinf.hStdOutput); CloseHandle(sinf.hStdError); CloseHandle(sinf.hStdInput); } # else char **argv = (char**)alloc_private(sizeof(char*)*4); argv[0] = cmd = "/bin/sh"; argv[1] = "-c"; argv[2] = cmdStr; argv[3] = NULL; int input[2], output[2], error[2]; if( pipe(input) || pipe(output) || pipe(error) ) neko_error(); p = (vprocess*)alloc_private(sizeof(vprocess)); p->pid = fork(); if( p->pid == -1 ) { do_close(input[0]); do_close(input[1]); do_close(output[0]); do_close(output[1]); do_close(error[0]); do_close(error[1]); neko_error(); } // child if( p->pid == 0 ) { close(input[1]); close(output[0]); close(error[0]); dup2(input[0],0); dup2(output[1],1); dup2(error[1],2); execvp(val_string(cmd),argv); fprintf(stderr,"Command not found : %s\n",val_string(cmd)); exit(1); } // parent do_close(input[0]); do_close(output[1]); do_close(error[1]); p->iwrite = input[1]; p->oread = output[0]; p->eread = error[0]; # endif { value vp = alloc_abstract(k_process,p); val_gc(vp,free_process); return vp; } }
GSAPI bool gunderscript_import_bytecode(Gunderscript * instance, char * fileName) { DSValue value; FILE * inFile = fopen(fileName, "r"); GSByteCodeHeader header; int i = 0; if(inFile == NULL) { instance->err = GUNDERSCRIPTERR_BAD_FILE_OPEN_READ; return false; } /* read header */ if(fread(&header, sizeof(GSByteCodeHeader), 1, inFile) != 1) { instance->err = GUNDERSCRIPTERR_BAD_FILE_READ; fclose(inFile); return false; } /* check for header */ if(strcmp(header.header, GS_BYTECODE_HEADER) != 0) { instance->err = GUNDERSCRIPTERR_NOT_BYTECODE_FILE; fclose(inFile); return false; } /* check that this build is the same as the one that created the file */ if(strcmp(header.buildDate, GUNDERSCRIPT_BUILD_DATE) != 0) { instance->err = GUNDERSCRIPTERR_INCORRECT_RUNTIME_VERSION; fclose(inFile); return false; } /* check that the number of functions isn't negative or zero */ if(header.numFunctions < 1) { instance->err = GUNDERSCRIPTERR_CORRUPTED_BYTECODE; return false; } /* import the exported functions definitions (script entry points) */ for(i = 0; i < header.numFunctions; i++) { VMFunc * currentFunc = calloc(1, sizeof(VMFunc)); char functionName[GS_MAX_FUNCTION_NAME_LEN]; char functionNameLen; bool prevValue = false; /* check if VMFunc alloc failed */ if(currentFunc == NULL) { instance->err = GUNDERSCRIPTERR_ALLOC_FAILED; fclose(inFile); return false; } /* read function name length */ if(fread(&functionNameLen, sizeof(char), 1, inFile) != 1) { instance->err = GUNDERSCRIPTERR_BAD_FILE_READ; return false; } /* check function name length */ if(functionNameLen > GS_MAX_FUNCTION_NAME_LEN) { instance->err = GUNDERSCRIPTERR_CORRUPTED_BYTECODE; fclose(inFile); return false; } /* read function name */ if(fread(&functionName, sizeof(char), functionNameLen, inFile) != functionNameLen) { instance->err = GUNDERSCRIPTERR_BAD_FILE_READ; fclose(inFile); return false; } /* read from file into new VMFunc */ value.pointerVal = currentFunc; if(fread(currentFunc, sizeof(VMFunc), 1, inFile) != 1) { instance->err = GUNDERSCRIPTERR_BAD_FILE_READ; fclose(inFile); return false; } /* put functions into VM functions hashtable */ if(!ht_put_raw_key(vm_functions(instance->vm), functionName, functionNameLen, &value, NULL, &prevValue)) { instance->err = GUNDERSCRIPTERR_ALLOC_FAILED; fclose(inFile); return false; } /* check for duplicate function names */ if(prevValue) { instance->err = GUNDERSCRIPTERR_CORRUPTED_BYTECODE; fclose(inFile); return false; } } /* make space in buffer for the bytecode */ if(!buffer_resize(vm_buffer(instance->vm), header.byteCodeLen)) { instance->err = GUNDERSCRIPTERR_ALLOC_FAILED; fclose(inFile); return false; } /* read raw bytecode from end of bytecode file */ { int c, i; for(i = 0; (c = fgetc(inFile)) != -1; i++) { buffer_append_char(vm_buffer(instance->vm), (char)c); } if(i != (header.byteCodeLen)) { instance->err = GUNDERSCRIPTERR_BAD_FILE_READ; fclose(inFile); return false; } } fclose(inFile); return true; }
/** process_run : cmd:string -> args:string array -> 'process <doc> Start a process using a command and the specified arguments. </doc> **/ CAMLprim value process_run( value cmd, value vargs ) { int i; vprocess *p; val_check(cmd,string); val_check(vargs,array); # ifdef _WIN32 { SECURITY_ATTRIBUTES sattr; STARTUPINFO sinf; HANDLE proc = GetCurrentProcess(); HANDLE oread,eread,iwrite; // creates commandline buffer b = alloc_buffer(NULL); char *sargs; buffer_append_char(b,'"'); buffer_append_str(b,val_string(cmd)); buffer_append_char(b,'"'); for(i=0;i<val_array_size(vargs);i++) { value v = val_array_ptr(vargs)[i]; int j,len; val_check(v,string); len = val_strlen(v); buffer_append_str(b," \""); for(j=0;j<len;j++) { char c = val_string(v)[j]; switch( c ) { case '"': buffer_append_str(b,"\\\""); break; case '\\': buffer_append_str(b,"\\\\"); break; default: buffer_append_char(b,c); break; } } buffer_append_char(b,'"'); } sargs = buffer_to_string(b); p = (vprocess*)alloc_private(sizeof(vprocess)); // startup process sattr.nLength = sizeof(sattr); sattr.bInheritHandle = TRUE; sattr.lpSecurityDescriptor = NULL; memset(&sinf,0,sizeof(sinf)); sinf.cb = sizeof(sinf); sinf.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; sinf.wShowWindow = SW_HIDE; CreatePipe(&oread,&sinf.hStdOutput,&sattr,0); CreatePipe(&eread,&sinf.hStdError,&sattr,0); CreatePipe(&sinf.hStdInput,&iwrite,&sattr,0); DuplicateHandle(proc,oread,proc,&p->oread,0,FALSE,DUPLICATE_SAME_ACCESS); DuplicateHandle(proc,eread,proc,&p->eread,0,FALSE,DUPLICATE_SAME_ACCESS); DuplicateHandle(proc,iwrite,proc,&p->iwrite,0,FALSE,DUPLICATE_SAME_ACCESS); CloseHandle(oread); CloseHandle(eread); CloseHandle(iwrite); if( !CreateProcess(NULL,val_string(sargs),NULL,NULL,TRUE,0,NULL,NULL,&sinf,&p->pinf) ) { CloseHandle(p->eread); CloseHandle(p->oread); CloseHandle(p->iwrite); free(sargs); neko_error(); } free(sargs); // close unused pipes CloseHandle(sinf.hStdOutput); CloseHandle(sinf.hStdError); CloseHandle(sinf.hStdInput); } # else char **argv = (char**)alloc_private(sizeof(char*)*(val_array_size(vargs)+2)); argv[0] = val_string(cmd); for(i=0;i<val_array_size(vargs);i++) { value v = val_array_ptr(vargs)[i]; val_check(v,string); argv[i+1] = val_string(v); } argv[i+1] = NULL; int input[2], output[2], error[2]; if( pipe(input) || pipe(output) || pipe(error) ) neko_error(); p = (vprocess*)alloc_private(sizeof(vprocess)); p->pid = fork(); if( p->pid == -1 ) { do_close(input[0]); do_close(input[1]); do_close(output[0]); do_close(output[1]); do_close(error[0]); do_close(error[1]); neko_error(); } // child if( p->pid == 0 ) { close(input[1]); close(output[0]); close(error[0]); dup2(input[0],0); dup2(output[1],1); dup2(error[1],2); execvp(val_string(cmd),argv); fprintf(stderr,"Command not found : %s\n",val_string(cmd)); exit(1); } // parent do_close(input[0]); do_close(output[1]); do_close(error[1]); p->iwrite = input[1]; p->oread = output[0]; p->eread = error[0]; # endif { value vp = alloc_abstract(k_process,p); val_gc(vp,free_process); return vp; } }