int asn1c_emit_constraint_checking_code(arg_t *arg) { asn1cnst_range_t *r_size; asn1cnst_range_t *r_value; asn1p_expr_t *expr = arg->expr; asn1p_expr_type_e etype; asn1p_constraint_t *ct; int got_something = 0; int alphabet_table_compiled; int produce_st = 0; int ulong_optimize = 0; ct = expr->combined_constraints; if(ct == NULL) return 1; /* No additional constraints defined */ etype = _find_terminal_type(arg); r_value=asn1constraint_compute_PER_range(etype, ct, ACT_EL_RANGE,0,0,0); r_size =asn1constraint_compute_PER_range(etype, ct, ACT_CT_SIZE, 0,0,0); if(r_value) { if(r_value->incompatible || r_value->empty_constraint || (r_value->left.type == ARE_MIN && r_value->right.type == ARE_MAX) || (etype == ASN_BASIC_BOOLEAN && r_value->left.value == 0 && r_value->right.value == 1) ) { asn1constraint_range_free(r_value); r_value = 0; } } if(r_size) { if(r_size->incompatible || r_size->empty_constraint || (r_size->left.value == 0 /* or .type == MIN */ && r_size->right.type == ARE_MAX) ) { asn1constraint_range_free(r_size); r_size = 0; } } /* * Do we really need an "*st = sptr" pointer? */ switch(etype) { case ASN_BASIC_INTEGER: case ASN_BASIC_ENUMERATED: if(asn1c_type_fits_long(arg, arg->expr) == FL_NOTFIT) produce_st = 1; break; case ASN_BASIC_REAL: if(!(arg->flags & A1C_USE_NATIVE_TYPES)) produce_st = 1; break; case ASN_BASIC_BIT_STRING: case ASN_BASIC_OCTET_STRING: produce_st = 1; break; default: if(etype & ASN_STRING_MASK) produce_st = 1; break; } if(produce_st) { char *tname = asn1c_type_name(arg, arg->expr, TNF_SAFE); OUT("const %s_t *st = (const %s_t *)sptr;\n", tname, tname); } if(r_size || r_value) { if(r_size) { OUT("size_t size;\n"); } if(r_value) switch(etype) { case ASN_BASIC_INTEGER: case ASN_BASIC_ENUMERATED: if(native_long_sign(r_value) >= 0) { ulong_optimize = ulong_optimization(etype, r_size, r_value); if(!ulong_optimize) { OUT("unsigned long value;\n"); } } else { OUT("long value;\n"); } break; case ASN_BASIC_REAL: OUT("double value;\n"); break; case ASN_BASIC_BOOLEAN: OUT("BOOLEAN_t value;\n"); break; default: break; } } OUT("\n"); /* * Protection against null input. */ OUT("if(!sptr) {\n"); INDENT(+1); OUT("_ASN_CTFAIL(app_key, td, sptr,\n"); OUT("\t\"%%s: value not given (%%s:%%d)\",\n"); OUT("\ttd->name, __FILE__, __LINE__);\n"); OUT("return -1;\n"); INDENT(-1); OUT("}\n"); OUT("\n"); if((r_value) && (!ulong_optimize)) emit_value_determination_code(arg, etype, r_value); if(r_size) emit_size_determination_code(arg, etype); INDENT(-1); REDIR(OT_CTABLES); /* Emit FROM() tables */ alphabet_table_compiled = (asn1c_emit_constraint_tables(arg, r_size?1:0) == 1); REDIR(OT_CODE); INDENT(+1); /* * Optimization for unsigned longs. */ if(ulong_optimize) { OUT("\n"); OUT("/* Constraint check succeeded */\n"); OUT("return 0;\n"); return 0; } /* * Here is an if() {} else {} consrtaint checking code. */ OUT("\n"); OUT("if("); INDENT(+1); if(r_size) { if(got_something++) { OUT("\n"); OUT(" && "); } OUT("("); emit_range_comparison_code(arg, r_size, "size", 0, -1); OUT(")"); } if(r_value) { if(got_something++) { OUT("\n"); OUT(" && "); } OUT("("); if(etype == ASN_BASIC_BOOLEAN) emit_range_comparison_code(arg, r_value, "value", 0, 1); else emit_range_comparison_code(arg, r_value, "value", -1, -1); OUT(")"); } if(alphabet_table_compiled) { if(got_something++) { OUT("\n"); OUT(" && "); } OUT("!check_permitted_alphabet_%d(%s)", arg->expr->_type_unique_index, produce_st ? "st" : "sptr"); } if(!got_something) { OUT("1 /* No applicable constraints whatsoever */"); OUT(") {\n"); INDENT(-1); INDENTED(OUT("/* Nothing is here. See below */\n")); OUT("}\n"); OUT("\n"); return 1; } INDENT(-1); OUT(") {\n"); INDENT(+1); switch(etype) { case ASN_CONSTR_SEQUENCE_OF: case ASN_CONSTR_SET_OF: OUT("/* Perform validation of the inner elements */\n"); OUT("return td->check_constraints(td, sptr, ctfailcb, app_key);\n"); break; default: OUT("/* Constraint check succeeded */\n"); OUT("return 0;\n"); } INDENT(-1); OUT("} else {\n"); INDENT(+1); OUT("_ASN_CTFAIL(app_key, td, sptr,\n"); OUT("\t\"%%s: constraint failed (%%s:%%d)\",\n"); OUT("\ttd->name, __FILE__, __LINE__);\n"); OUT("return -1;\n"); INDENT(-1); OUT("}\n"); return 0; }
int job_start(struct job *j) { struct proc *p; struct redir *redir_iter; int pipey[2] = { -1, -1 }; #define REDIR(a, b) \ do{ \ if(a != b){ \ /* close b and copy a into b */ \ if(dup2(a, b) == -1) \ perror("dup2()"); \ if(close(a) == -1) \ perror("close()"); \ } \ }while(0) for(redir_iter = j->redir; redir_iter; redir_iter = redir_iter->next){ int fd; if(redir_iter->fname){ fd = open(redir_iter->fname, O_WRONLY | O_CREAT | O_TRUNC); /* FIXME: only out for now - need "<" and ">>" */ if(fd == -1){ fprintf(stderr, "ush: open %s: %s\n", redir_iter->fname, strerror(errno)); /* FIXME: close all other fds */ return 1; } }else{ fd = redir_iter->fd_out; } fprintf(stderr, "job_start(): REDIR(%d [%s], %d)\n", fd, redir_iter->fname, redir_iter->fd_in); REDIR(fd, redir_iter->fd_in); } j->proc->in = STDIN_FILENO; for(p = j->proc; p; p = p->next){ p->err = STDERR_FILENO; if(p->next){ if(pipe(pipey) < 0){ perror("pipe()"); goto bail; } p->out = pipey[1]; p->next->in = pipey[0]; }else{ p->out = STDOUT_FILENO; } /* TODO: cd, fg, rehash */ switch(p->pid = fork()){ case 0: p->pid = getpid(); REDIR(p->in, STDIN_FILENO); REDIR(p->out, STDOUT_FILENO); REDIR(p->err, STDERR_FILENO); #undef REDIR job_close_fds(j, p->next); proc_exec(p, j->gid); break; /* unreachable */ case -1: perror("fork()"); goto bail; default: if(interactive){ if(!j->gid) j->gid = p->pid; setpgid(p->pid, j->gid); } p->state = PROC_RUN; } } /* close our access to all these pipes */ job_close_fds(j, NULL); j->state = JOB_RUNNING; return 0; bail: fprintf(stderr, "warning: error starting job: %s\n", strerror(errno)); for(; p; p = p->next) p->state = PROC_FIN; job_close_fds(j, NULL); job_sig(j, SIGCONT); return 1; }