void cache_del( ITEM *item ) { CACHE *cache = list_value( item ); hash_del( _main->cache->hash, (UCHAR *)cache->target, SHA1_SIZE ); list_del( _main->cache->list, item ); myfree( cache ); }
static void post_jail_init(char *unused_name, char **unused_argv) { const NAME_CODE actions[] = { PSC_NAME_ACT_DROP, PSC_ACT_DROP, PSC_NAME_ACT_ENFORCE, PSC_ACT_ENFORCE, PSC_NAME_ACT_IGNORE, PSC_ACT_IGNORE, PSC_NAME_ACT_CONT, PSC_ACT_IGNORE, /* compatibility */ 0, -1, }; int cache_flags; const char *tmp; /* * This routine runs after the skeleton code has entered the chroot jail. * Prevent automatic process suicide after a limited number of client * requests. It is OK to terminate after a limited amount of idle time. */ var_use_limit = 0; /* * Workaround for parameters whose values may contain "$", and that have * a default of "$parametername". Not sure if it would be a good idea to * always to this in the mail_conf_raw(3) module. */ if (*var_psc_rej_footer == '$' && mail_conf_lookup(var_psc_rej_footer + 1)) { tmp = mail_conf_eval_once(var_psc_rej_footer); myfree(var_psc_rej_footer); var_psc_rej_footer = mystrdup(tmp); } if (*var_psc_exp_filter == '$' && mail_conf_lookup(var_psc_exp_filter + 1)) { tmp = mail_conf_eval_once(var_psc_exp_filter); myfree(var_psc_exp_filter); var_psc_exp_filter = mystrdup(tmp); } /* * Other one-time initialization. */ psc_temp = vstring_alloc(10); vstring_sprintf(psc_temp, "%s/%s", MAIL_CLASS_PRIVATE, var_smtpd_service); psc_smtpd_service_name = mystrdup(STR(psc_temp)); psc_dnsbl_init(); psc_early_init(); psc_smtpd_init(); if ((psc_blist_action = name_code(actions, NAME_CODE_FLAG_NONE, var_psc_blist_action)) < 0) msg_fatal("bad %s value: %s", VAR_PSC_BLIST_ACTION, var_psc_blist_action); if ((psc_dnsbl_action = name_code(actions, NAME_CODE_FLAG_NONE, var_psc_dnsbl_action)) < 0) msg_fatal("bad %s value: %s", VAR_PSC_DNSBL_ACTION, var_psc_dnsbl_action); if ((psc_pregr_action = name_code(actions, NAME_CODE_FLAG_NONE, var_psc_pregr_action)) < 0) msg_fatal("bad %s value: %s", VAR_PSC_PREGR_ACTION, var_psc_pregr_action); if ((psc_pipel_action = name_code(actions, NAME_CODE_FLAG_NONE, var_psc_pipel_action)) < 0) msg_fatal("bad %s value: %s", VAR_PSC_PIPEL_ACTION, var_psc_pipel_action); if ((psc_nsmtp_action = name_code(actions, NAME_CODE_FLAG_NONE, var_psc_nsmtp_action)) < 0) msg_fatal("bad %s value: %s", VAR_PSC_NSMTP_ACTION, var_psc_nsmtp_action); if ((psc_barlf_action = name_code(actions, NAME_CODE_FLAG_NONE, var_psc_barlf_action)) < 0) msg_fatal("bad %s value: %s", VAR_PSC_BARLF_ACTION, var_psc_barlf_action); /* Fail "closed" on error. */ psc_wlist_if = addr_match_list_init(MATCH_FLAG_RETURN, var_psc_wlist_if); /* * Start the cache maintenance pseudo thread last. Early cleanup makes * verbose logging more informative (we get positive confirmation that * the cleanup thread runs). */ cache_flags = DICT_CACHE_FLAG_STATISTICS; if (msg_verbose > 1) cache_flags |= DICT_CACHE_FLAG_VERBOSE; if (psc_cache_map != 0 && var_psc_cache_scan > 0) dict_cache_control(psc_cache_map, DICT_CACHE_CTL_FLAGS, cache_flags, DICT_CACHE_CTL_INTERVAL, var_psc_cache_scan, DICT_CACHE_CTL_VALIDATOR, psc_cache_validator, DICT_CACHE_CTL_CONTEXT, (char *) 0, DICT_CACHE_CTL_END); /* * Pre-compute the minimal and maximal TTL. */ psc_min_ttl = PSC_MIN(PSC_MIN(var_psc_pregr_ttl, var_psc_dnsbl_ttl), PSC_MIN(PSC_MIN(var_psc_pipel_ttl, var_psc_nsmtp_ttl), var_psc_barlf_ttl)); psc_max_ttl = PSC_MAX(PSC_MAX(var_psc_pregr_ttl, var_psc_dnsbl_ttl), PSC_MAX(PSC_MAX(var_psc_pipel_ttl, var_psc_nsmtp_ttl), var_psc_barlf_ttl)); /* * Pre-compute the stress and normal command time limits. */ mail_conf_update(VAR_STRESS, "yes"); psc_stress_cmd_time_limit = get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0); psc_stress_greet_wait = get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0); mail_conf_update(VAR_STRESS, ""); psc_normal_cmd_time_limit = get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0); psc_normal_greet_wait = get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0); psc_lowat_check_queue_length = .7 * var_psc_pre_queue_limit; psc_hiwat_check_queue_length = .9 * var_psc_pre_queue_limit; if (msg_verbose) msg_info(VAR_PSC_CMD_TIME ": stress=%d normal=%d lowat=%d hiwat=%d", psc_stress_cmd_time_limit, psc_normal_cmd_time_limit, psc_lowat_check_queue_length, psc_hiwat_check_queue_length); if (psc_lowat_check_queue_length == 0) msg_panic("compiler error: 0.7 * %d = %d", var_psc_pre_queue_limit, psc_lowat_check_queue_length); if (psc_hiwat_check_queue_length == 0) msg_panic("compiler error: 0.9 * %d = %d", var_psc_pre_queue_limit, psc_hiwat_check_queue_length); /* * Per-client concurrency. */ psc_client_concurrency = htable_create(var_psc_pre_queue_limit); }
void pcf_edit_master(int mode, int argc, char **argv) { const char *myname = "pcf_edit_master"; char *path; EDIT_FILE *ep; VSTREAM *src; VSTREAM *dst; VSTRING *line_buf = vstring_alloc(100); VSTRING *parse_buf = vstring_alloc(100); int lineno; PCF_MASTER_ENT *new_entry; VSTRING *full_entry_buf = vstring_alloc(100); char *cp; char *pattern; int service_name_type_matched; const char *err; PCF_MASTER_EDIT_REQ *edit_reqs; PCF_MASTER_EDIT_REQ *req; int num_reqs = argc; const char *edit_opts = "-Me, -Fe, -Pe, -X, or -#"; char *service_name; char *service_type; /* * Sanity check. */ if (num_reqs <= 0) msg_panic("%s: empty argument list", myname); /* * Preprocessing: split pattern=value, then split the pattern components. */ edit_reqs = (PCF_MASTER_EDIT_REQ *) mymalloc(sizeof(*edit_reqs) * num_reqs); for (req = edit_reqs; *argv != 0; req++, argv++) { req->match_count = 0; req->raw_text = *argv; cp = req->parsed_text = mystrdup(req->raw_text); if (strchr(cp, '\n') != 0) msg_fatal("%s accept no multi-line input", edit_opts); while (ISSPACE(*cp)) cp++; if (*cp == '#') msg_fatal("%s accept no comment input", edit_opts); /* Separate the pattern from the value. */ if (mode & PCF_EDIT_CONF) { if ((err = split_nameval(cp, &pattern, &req->edit_value)) != 0) msg_fatal("%s: \"%s\"", err, req->raw_text); if ((mode & PCF_MASTER_PARAM) && req->edit_value[strcspn(req->edit_value, PCF_MASTER_BLANKS)]) msg_fatal("whitespace in parameter value: \"%s\"", req->raw_text); } else if (mode & (PCF_COMMENT_OUT | PCF_EDIT_EXCL)) { if (strchr(cp, '=') != 0) msg_fatal("-X or -# requires names without value"); pattern = cp; trimblanks(pattern, 0); req->edit_value = 0; } else { msg_panic("%s: unknown mode %d", myname, mode); } #define PCF_MASTER_MASK (PCF_MASTER_ENTRY | PCF_MASTER_FLD | PCF_MASTER_PARAM) /* * Split name/type or name/type/whatever pattern into components. */ switch (mode & PCF_MASTER_MASK) { case PCF_MASTER_ENTRY: if ((req->service_pattern = pcf_parse_service_pattern(pattern, 2, 2)) == 0) msg_fatal("-Me, -MX or -M# requires service_name/type"); break; case PCF_MASTER_FLD: if ((req->service_pattern = pcf_parse_service_pattern(pattern, 3, 3)) == 0) msg_fatal("-Fe or -FX requires service_name/type/field_name"); req->field_number = pcf_parse_field_pattern(req->service_pattern->argv[2]); if (pcf_is_magic_field_pattern(req->field_number)) msg_fatal("-Fe does not accept wild-card field name"); if ((mode & PCF_EDIT_CONF) && req->field_number < PCF_MASTER_FLD_CMD && req->edit_value[strcspn(req->edit_value, PCF_MASTER_BLANKS)]) msg_fatal("-Fe does not accept whitespace in non-command field"); break; case PCF_MASTER_PARAM: if ((req->service_pattern = pcf_parse_service_pattern(pattern, 3, 3)) == 0) msg_fatal("-Pe or -PX requires service_name/type/parameter"); req->param_pattern = req->service_pattern->argv[2]; if (PCF_IS_MAGIC_PARAM_PATTERN(req->param_pattern)) msg_fatal("-Pe does not accept wild-card parameter name"); if ((mode & PCF_EDIT_CONF) && req->edit_value[strcspn(req->edit_value, PCF_MASTER_BLANKS)]) msg_fatal("-Pe does not accept whitespace in parameter value"); break; default: msg_panic("%s: unknown edit mode %d", myname, mode); } } /* * Open a temp file for the result. This uses a deterministic name so we * don't leave behind thrash with random names. */ pcf_set_config_dir(); path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0); if ((ep = edit_file_open(path, O_CREAT | O_WRONLY, 0644)) == 0) msg_fatal("open %s%s: %m", path, EDIT_FILE_SUFFIX); dst = ep->tmp_fp; /* * Open the original file for input. */ if ((src = vstream_fopen(path, O_RDONLY, 0)) == 0) { /* OK to delete, since we control the temp file name exclusively. */ (void) unlink(ep->tmp_path); msg_fatal("open %s for reading: %m", path); } /* * Copy original file to temp file, while replacing service entries on * the fly. */ service_name_type_matched = 0; new_entry = 0; lineno = 0; while ((cp = pcf_next_cf_line(parse_buf, src, dst, &lineno)) != 0) { vstring_strcpy(line_buf, STR(parse_buf)); /* * Copy, skip or replace continued text. */ if (cp > STR(parse_buf)) { if (service_name_type_matched == 0) vstream_fputs(STR(line_buf), dst); else if (mode & PCF_COMMENT_OUT) vstream_fprintf(dst, "#%s", STR(line_buf)); } /* * Copy or replace (start of) logical line. */ else { service_name_type_matched = 0; /* * Parse out the service name and type. */ if ((service_name = mystrtok(&cp, PCF_MASTER_BLANKS)) == 0 || (service_type = mystrtok(&cp, PCF_MASTER_BLANKS)) == 0) msg_fatal("file %s: line %d: specify service name and type " "on the same line", path, lineno); if (strchr(service_name, '=')) msg_fatal("file %s: line %d: service name syntax \"%s\" is " "unsupported with %s", path, lineno, service_name, edit_opts); if (service_type[strcspn(service_type, "=/")] != 0) msg_fatal("file %s: line %d: " "service type syntax \"%s\" is unsupported with %s", path, lineno, service_type, edit_opts); /* * Match each service pattern. */ for (req = edit_reqs; req < edit_reqs + num_reqs; req++) { if (PCF_MATCH_SERVICE_PATTERN(req->service_pattern, service_name, service_type)) { service_name_type_matched = 1; /* Sticky flag */ req->match_count += 1; /* * Generate replacement master.cf entries. */ if ((mode & PCF_EDIT_CONF) || ((mode & PCF_MASTER_PARAM) && (mode & PCF_EDIT_EXCL))) { switch (mode & PCF_MASTER_MASK) { /* * Replace master.cf entry field or parameter * value. */ case PCF_MASTER_FLD: case PCF_MASTER_PARAM: if (new_entry == 0) { /* Gobble up any continuation lines. */ pcf_gobble_cf_line(full_entry_buf, line_buf, src, dst, &lineno); new_entry = (PCF_MASTER_ENT *) mymalloc(sizeof(*new_entry)); if ((err = pcf_parse_master_entry(new_entry, STR(full_entry_buf))) != 0) msg_fatal("file %s: line %d: %s", path, lineno, err); } if (mode & PCF_MASTER_FLD) { pcf_edit_master_field(new_entry, req->field_number, req->edit_value); } else { pcf_edit_master_param(new_entry, mode, req->param_pattern, req->edit_value); } break; /* * Replace entire master.cf entry. */ case PCF_MASTER_ENTRY: if (new_entry != 0) pcf_free_master_entry(new_entry); new_entry = (PCF_MASTER_ENT *) mymalloc(sizeof(*new_entry)); if ((err = pcf_parse_master_entry(new_entry, req->edit_value)) != 0) msg_fatal("%s: \"%s\"", err, req->raw_text); break; default: msg_panic("%s: unknown edit mode %d", myname, mode); } } } } /* * Pass through or replace the current input line. */ if (new_entry) { pcf_print_master_entry(dst, PCF_FOLD_LINE, new_entry); pcf_free_master_entry(new_entry); new_entry = 0; } else if (service_name_type_matched == 0) { vstream_fputs(STR(line_buf), dst); } else if (mode & PCF_COMMENT_OUT) { vstream_fprintf(dst, "#%s", STR(line_buf)); } } } /* * Postprocessing: when editing entire service entries, generate new * entries for services not found. Otherwise (editing fields or * parameters), "service not found" is a fatal error. */ for (req = edit_reqs; req < edit_reqs + num_reqs; req++) { if (req->match_count == 0) { if ((mode & PCF_MASTER_ENTRY) && (mode & PCF_EDIT_CONF)) { new_entry = (PCF_MASTER_ENT *) mymalloc(sizeof(*new_entry)); if ((err = pcf_parse_master_entry(new_entry, req->edit_value)) != 0) msg_fatal("%s: \"%s\"", err, req->raw_text); pcf_print_master_entry(dst, PCF_FOLD_LINE, new_entry); pcf_free_master_entry(new_entry); } else if ((mode & PCF_MASTER_ENTRY) == 0) { msg_warn("unmatched service_name/type: \"%s\"", req->raw_text); } } } /* * When all is well, rename the temp file to the original one. */ if (vstream_fclose(src)) msg_fatal("read %s: %m", path); if (edit_file_close(ep) != 0) msg_fatal("close %s%s: %m", path, EDIT_FILE_SUFFIX); /* * Cleanup. */ myfree(path); vstring_free(line_buf); vstring_free(parse_buf); vstring_free(full_entry_buf); for (req = edit_reqs; req < edit_reqs + num_reqs; req++) { argv_free(req->service_pattern); myfree(req->parsed_text); } myfree((char *) edit_reqs); }
void cache_free( void ) { list_clear( _main->cache->list ); list_free( _main->cache->list ); hash_free( _main->cache->hash ); myfree( _main->cache, "cache_free" ); }
void subfind_potential_compute(int num, struct unbind_data *d, int phase, double weakly_bound_limit) { int i, j, k, sendTask, recvTask; int ndone, ndone_flag, dummy; int ngrp, place, nexport, nimport; double atime; /* allocate buffers to arrange communication */ All.BunchSize = (int) ((All.BufferSize * 1024 * 1024) / (sizeof(struct data_index) + sizeof(struct data_nodelist) + sizeof(struct gravdata_in) + sizeof(struct potdata_out) + sizemax(sizeof(struct gravdata_in), sizeof(struct potdata_out)))); DataIndexTable = (struct data_index *) mymalloc(All.BunchSize * sizeof(struct data_index)); DataNodeList = (struct data_nodelist *) mymalloc(All.BunchSize * sizeof(struct data_nodelist)); i = 0; /* beginn with this index */ do { for(j = 0; j < NTask; j++) { Send_count[j] = 0; Exportflag[j] = -1; } /* do local particles and prepare export list */ for(nexport = 0; i < num; i++) { if(phase == 1) if(P[d[i].index].v.DM_BindingEnergy <= weakly_bound_limit) continue; if(subfind_force_treeevaluate_potential(d[i].index, 0, &nexport, Send_count) < 0) break; } qsort(DataIndexTable, nexport, sizeof(struct data_index), data_index_compare); MPI_Allgather(Send_count, NTask, MPI_INT, Sendcount_matrix, NTask, MPI_INT, MPI_COMM_WORLD); for(j = 0, nimport = 0, Recv_offset[0] = 0, Send_offset[0] = 0; j < NTask; j++) { Recv_count[j] = Sendcount_matrix[j * NTask + ThisTask]; nimport += Recv_count[j]; if(j > 0) { Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1]; Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1]; } } GravDataGet = (struct gravdata_in *) mymalloc(nimport * sizeof(struct gravdata_in)); GravDataIn = (struct gravdata_in *) mymalloc(nexport * sizeof(struct gravdata_in)); /* prepare particle data for export */ for(j = 0; j < nexport; j++) { place = DataIndexTable[j].Index; for(k = 0; k < 3; k++) GravDataIn[j].Pos[k] = P[place].Pos[k]; for(k = 0; k < NODELISTLENGTH; k++) GravDataIn[j].NodeList[k] = DataNodeList[DataIndexTable[j].IndexGet].NodeList[k]; #ifdef UNEQUALSOFTENINGS GravDataIn[j].Type = P[place].Type; #ifdef ADAPTIVE_GRAVSOFT_FORGAS if(P[place].Type == 0) GravDataIn[j].Soft = SphP[place].Hsml; #endif #endif } /* exchange particle data */ for(ngrp = 1; ngrp < (1 << PTask); ngrp++) { sendTask = ThisTask; recvTask = ThisTask ^ ngrp; if(recvTask < NTask) { if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0) { /* get the particles */ MPI_Sendrecv(&GravDataIn[Send_offset[recvTask]], Send_count[recvTask] * sizeof(struct gravdata_in), MPI_BYTE, recvTask, TAG_POTENTIAL_A, &GravDataGet[Recv_offset[recvTask]], Recv_count[recvTask] * sizeof(struct gravdata_in), MPI_BYTE, recvTask, TAG_POTENTIAL_A, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } } } myfree(GravDataIn); PotDataResult = (struct potdata_out *) mymalloc(nimport * sizeof(struct potdata_out)); PotDataOut = (struct potdata_out *) mymalloc(nexport * sizeof(struct potdata_out)); /* now do the particles that were sent to us */ for(j = 0; j < nimport; j++) subfind_force_treeevaluate_potential(j, 1, &dummy, &dummy); if(i >= num) ndone_flag = 1; else ndone_flag = 0; MPI_Allreduce(&ndone_flag, &ndone, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); /* get the result */ for(ngrp = 1; ngrp < (1 << PTask); ngrp++) { sendTask = ThisTask; recvTask = ThisTask ^ ngrp; if(recvTask < NTask) { if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0) { /* send the results */ MPI_Sendrecv(&PotDataResult[Recv_offset[recvTask]], Recv_count[recvTask] * sizeof(struct potdata_out), MPI_BYTE, recvTask, TAG_POTENTIAL_B, &PotDataOut[Send_offset[recvTask]], Send_count[recvTask] * sizeof(struct potdata_out), MPI_BYTE, recvTask, TAG_POTENTIAL_B, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } } } /* add the results to the local particles */ for(j = 0; j < nexport; j++) { place = DataIndexTable[j].Index; P[place].u.DM_Potential += PotDataOut[j].Potential; } myfree(PotDataOut); myfree(PotDataResult); myfree(GravDataGet); } while(ndone < NTask); if(All.ComovingIntegrationOn) atime = All.Time; else atime = 1; for(i = 0; i < num; i++) { if(phase == 1) if(P[d[i].index].v.DM_BindingEnergy <= weakly_bound_limit) continue; P[d[i].index].u.DM_Potential += P[d[i].index].Mass / All.SofteningTable[P[d[i].index].Type]; P[d[i].index].u.DM_Potential *= All.G / atime; if(All.TotN_gas > 0 && (FOF_PRIMARY_LINK_TYPES & 1) == 0 && All.OmegaBaryon > 0) P[d[i].index].u.DM_Potential *= All.Omega0 / (All.Omega0 - All.OmegaBaryon); } myfree(DataNodeList); myfree(DataIndexTable); }
//é‡Šæ”¾å†…å˜ void ff_memfree (void *mf) { myfree(SRAMIN, mf); }
void * sockschild(struct clientparam* param) { int res; unsigned i=0; SOCKET s; unsigned size; SASIZETYPE sasize; unsigned char * buf=NULL; unsigned char c; unsigned char command=0; struct pollfd fds[3]; int ver=0; int havepass = 0; struct sockaddr_in sin; int len; param->req.sin_addr.s_addr = 0; param->service = S_SOCKS; if(!(buf = myalloc(BUFSIZE))) {RETURN(21);} memset(buf, 0, BUFSIZE); if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) { RETURN(401); } /* version */ param->service = ver; if(ver == 5){ if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */ for (; i; i--) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(442);} if (res == 2 && !param->srv->nouser) { havepass = res; } } buf[0] = 5; buf[1] = havepass; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);} if (havepass) { if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) { RETURN(412); } if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(443);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(444);}; buf[i] = 0; if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf); if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(446);}; buf[i] = 0; if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf); buf[0] = 1; buf[1] = 0; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);} } if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) { RETURN(421); } /* version */ } if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */ if(ver == 5){ if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */ c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */ } else { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(448);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(449);} buf[1] = (unsigned char) res; param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf; c = 1; } switch(c) { case 1: for (i = 0; i<4; i++){ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(450);} buf[i] = (unsigned char)res; } param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = *(unsigned long *)buf; if(command==1 && !param->req.sin_addr.s_addr) { RETURN(422); } myinet_ntoa(param->sins.sin_addr, (char *)buf); break; case 3: if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */ for (i=0; i<size; i++){ /* size < 256 */ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(452);} buf[i] = (unsigned char)res; } buf[i] = 0; param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf); if(command==1 && !param->req.sin_addr.s_addr) { RETURN(100); } break; default: RETURN(998); } if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); if (ver == 5) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(453);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(454);} buf[1] = (unsigned char) res; param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf; } else { sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(!param->srv->nouser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf); if(param->sins.sin_addr.s_addr && ntohl(param->sins.sin_addr.s_addr)<256){ param->service = S_SOCKS45; sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf); } } if(command == 1 && !param->req.sin_port) {RETURN(424);} param->sins.sin_family = AF_INET; switch(command) { case 1: param->operation = CONNECT; break; case 2: param->sins.sin_addr.s_addr = param->extip; param->sins.sin_port = param->extport?param->extport:param->req.sin_port; if ((param->remsock=so._socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);} param->operation = BIND; break; case 3: param->sins.sin_port = param->extport?param->extport:param->req.sin_port; param->sins.sin_addr.s_addr = param->extip; if ((param->remsock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} param->operation = UDPASSOC; break; default: RETURN(997); } if((res = (*param->srv->authfunc)(param))) {RETURN(res);} if(command > 1) { if(so._bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins))) { param->sins.sin_port = 0; if(so._bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins)))RETURN (12); #if SOCKSTRACE > 0 fprintf(stderr, "%s:%hu binded to communicate with server\n", inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port) ); fflush(stderr); #endif } sasize = sizeof(struct sockaddr_in); so._getsockname(param->remsock, (struct sockaddr *)¶m->sins, &sasize); if(command == 3) { param->ctrlsock = param->clisock; param->clisock = so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(param->clisock == INVALID_SOCKET) {RETURN(11);} sin.sin_family = AF_INET; sin.sin_addr.s_addr = param->srv->intip; sin.sin_port = htons(0); if(so._bind(param->clisock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))) {RETURN (12);} #if SOCKSTRACE > 0 fprintf(stderr, "%s:%hu binded to communicate with client\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif } } param->res = 0; CLEANRET: if(param->clisock != INVALID_SOCKET){ sasize = sizeof(struct sockaddr_in); if(command != 3) so._getsockname(param->remsock, (struct sockaddr *)&sin, &sasize); else so._getsockname(param->clisock, (struct sockaddr *)&sin, &sasize); #if SOCKSTRACE > 0 fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n", param->res, commands[command], inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif if(ver == 5){ buf[0] = 5; buf[1] = param->res%10; buf[2] = 0; buf[3] = 1; memcpy(buf+4, &sin.sin_addr.s_addr, 4); memcpy(buf+8, &sin.sin_port, 2); socksend((command == 3)?param->ctrlsock:param->clisock, buf, 10, conf.timeouts[STRING_S]); } else{ buf[0] = 0; buf[1] = 90 + (param->res%10); memcpy(buf+2, &sin.sin_port, 2); memcpy(buf+4, &sin.sin_addr.s_addr, 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } if (param->res == 0) { switch(command) { case 1: if(param->redirectfunc){ if(buf)myfree(buf); return (*param->redirectfunc)(param); } param->res = sockmap(param, conf.timeouts[CONNECTION_L]); break; case 2: so._listen (param->remsock, 1); fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[0].events = fds[1].events = POLLIN; res = so._poll(fds, 2, conf.timeouts[(param->req.sin_addr.s_addr)?CONNECTION_S:CONNECTION_L] * 1000); if (res < 1 || fds[1].revents) { res = 460; break; } sasize = sizeof(param->sins); s = so._accept(param->remsock, (struct sockaddr *)¶m->sins, &sasize); so._closesocket(param->remsock); param->remsock = s; if(s == INVALID_SOCKET) { param->res = 462; break; } if(param->req.sin_addr.s_addr && param->req.sin_addr.s_addr != param->sins.sin_addr.s_addr) { param->res = 470; break; } #if SOCKSTRACE > 0 fprintf(stderr, "Sending incoming connection to client with code %d for %s with %s:%hu\n", param->res, commands[command], inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port) ); fflush(stderr); #endif if(ver == 5){ memcpy (buf+4, ¶m->sins.sin_addr, 4); memcpy (buf+8, ¶m->sins.sin_port, 2); socksend(param->clisock, buf, 10, conf.timeouts[STRING_S]); } else { memcpy (buf+2, ¶m->sins.sin_port, 2); memcpy (buf+4, ¶m->sins.sin_addr, 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } param->res = sockmap(param, conf.timeouts[CONNECTION_S]); break; case 3: param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr; param->sins.sin_port = param->req.sin_port; myfree(buf); if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);} for(;;){ fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[2].fd = param->ctrlsock; fds[2].events = fds[1].events = fds[0].events = POLLIN; res = so._poll(fds, 3, conf.timeouts[CONNECTION_L]*1000); if(res <= 0) { param->res = 463; break; } if (fds[2].revents) { param->res = 0; break; } if (fds[1].revents) { sasize = sizeof(struct sockaddr_in); if((len = so._recvfrom(param->clisock, buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) { param->res = 464; break; } if(sin.sin_addr.s_addr != param->sinc.sin_addr.s_addr){ param->res = 465; break; } if(buf[0] || buf[1] || buf[2]) { param->res = 466; break; } switch(buf[3]) { case 1: i = 8; memcpy(¶m->sins.sin_addr.s_addr, buf+4, 4); break; case 3: size = buf[4]; for (i=4; size; i++, size--){ buf[i] = buf[i+1]; } buf[i++] = 0; param->sins.sin_addr.s_addr = getip(buf+4); break; default: RETURN(996); } memcpy(¶m->sins.sin_port, buf+i, 2); i+=2; sasize = sizeof(param->sins); if(len > (int)i){ if(socksendto(param->remsock, ¶m->sins, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){ param->res = 467; break; } param->statscli+=(len - i); param->nwrites++; #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n", inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port), (len - i), i ); fprintf(stderr, "client address is assumed to be %s:%hu\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif } } if (fds[0].revents) { struct sockaddr_in tsin; sasize = sizeof(tsin); buf[0]=buf[1]=buf[2]=0; buf[3]=1; if((len = so._recvfrom(param->remsock, buf+10, 65535 - 10, 0, (struct sockaddr *)&tsin, &sasize)) <= 0) { param->res = 468; break; } param->statssrv+=len; param->nreads++; memcpy(buf+4, &tsin.sin_addr.s_addr, 4); memcpy(buf+8, &tsin.sin_port, 2); sasize = sizeof(param->sins); if(socksendto(param->clisock, &sin, buf, len + 10, conf.timeouts[SINGLEBYTE_L]*1000) <=0){ param->res = 469; break; } #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed to client from %s:%hu size %d\n", inet_ntoa(tsin.sin_addr), ntohs(tsin.sin_port), len ); fflush(stderr); #endif } } break; default: param->res = 417; break; } } } if(command > 3) command = 0; if(buf){ sprintf((char *)buf, "%s ", commands[command]); if(param->hostname){ sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname); } else myinet_ntoa(param->req.sin_addr, (char *)buf+strlen((char *)buf)); sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(param->req.sin_port)); (*param->srv->logfunc)(param, buf); myfree(buf); } freeparam(param); return (NULL); }
extern DATASET *read_seq_file( AjPSeqall seqa, /* name of file to open */ char *alpha, /* alphabet used in sequences */ BOOLEAN use_comp, /* use complementary strands, too */ double seqfrac /* fraction of input sequences to use */ ) { int i, j, pcol; /*FILE *data_file;*/ /* file with samples to read */ char *sample_name; /* name of sample read */ char *sample_de; /* descriptor text for sample */ char *sequence; /* sequence read */ int length; /* length of sequence */ BOOLEAN error=FALSE; /* none yet */ SAMPLE *sample; /* sample created */ DATASET *dataset; /* dataset created */ int n_samples=0; /* number of samples read */ double *seq_weights=NULL; /* sequence weights */ int n_wgts=0; /* number of sequence weights given */ /* create a hash table of sequence names */ if (!ht_seq_names) ht_seq_names = hash_create(DATA_HASH_SIZE); /* create a dataset */ dataset = (DATASET *) malloc(sizeof(DATASET)); dataset->alength = strlen(alpha); dataset->alphabet = alpha; dataset->pal = 0; /* not looking for palindromes */ /* initialize maximum length of sequences */ dataset->max_slength = 0; dataset->min_slength = 10000000; dataset->n_samples = 0; /* no samples yet */ dataset->samples = NULL; /* no samples */ while (read_sequence(seqa, &sample_name, &sample_de, &sequence, &length)) { /* skip sequence if an error occurred */ if (length < 0) continue; /* parse weights if given; make (more than enough) room in array */ if (strcmp(sample_name, "WEIGHTS")==0) { double wgt; char *wgt_str = sample_de; Resize(seq_weights, n_wgts+strlen(wgt_str), double); while (sscanf(wgt_str, "%lf", &wgt) == 1) { if (wgt <= 0 || wgt > 1) { fprintf(stderr, "Weights must be larger than zero and no greater than 1.\n"); exit(1); } seq_weights[n_wgts++] = wgt; /* save weight */ wgt_str += strspn(wgt_str, " "); /* skip white */ wgt_str += strcspn(wgt_str, " "); /* skip token */ } myfree(sample_name); myfree(sample_de); myfree(sequence); continue; } /* ignore duplicate (same sample name) sequences */ if (hash_lookup(sample_name, 0, ht_seq_names)) { fprintf(stderr, "Skipping %s\n", sample_name); myfree(sample_name); myfree(sample_de); myfree(sequence); continue; } hash_insert(sample_name, 0, ht_seq_names); /* put name in hash table */ n_samples++; /* see if sequence will be used in random sample; store it if yes */ if (drand48() >= 1 - seqfrac) { /* create the sample */ sample = create_sample(alpha, length, sample_name, sequence); if (sample == NULL) {error = TRUE; continue;} /* record maximum length of actual sequences */ dataset->max_slength = MAX(sample->length, dataset->max_slength); dataset->min_slength = MIN(sample->length, dataset->min_slength); /* put the sample in the array of samples */ if ((dataset->n_samples % RCHUNK) == 0) { Resize(dataset->samples, dataset->n_samples + RCHUNK, SAMPLE *); }
int bounce_workaround(LOCAL_STATE state) { const char *myname = "bounce_workaround"; VSTRING *canon_owner = 0; int rcpt_stat; /* * Look up the substitute sender address. */ if (var_ownreq_special) { char *stripped_recipient; char *owner_alias; const char *owner_expansion; #define FIND_OWNER(lhs, rhs, addr) { \ lhs = concatenate("owner-", addr, (char *) 0); \ (void) split_at_right(lhs, '@'); \ rhs = maps_find(alias_maps, lhs, DICT_FLAG_NONE); \ } FIND_OWNER(owner_alias, owner_expansion, state.msg_attr.rcpt.address); if (alias_maps->error == 0 && owner_expansion == 0 && (stripped_recipient = strip_addr(state.msg_attr.rcpt.address, (char **) 0, var_rcpt_delim)) != 0) { myfree(owner_alias); FIND_OWNER(owner_alias, owner_expansion, stripped_recipient); myfree(stripped_recipient); } if (alias_maps->error == 0 && owner_expansion != 0) { canon_owner = canon_addr_internal(vstring_alloc(10), var_exp_own_alias ? owner_expansion : owner_alias); SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level); } myfree(owner_alias); if (alias_maps->error != 0) /* At this point, canon_owner == 0. */ return (defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr))); } /* * Send a delivery status notification with a single recipient to the * substitute sender address, before completion of the delivery request. */ if (canon_owner) { rcpt_stat = bounce_one(BOUNCE_FLAGS(state.request), BOUNCE_ONE_ATTR(state.msg_attr)); vstring_free(canon_owner); } /* * Send a regular delivery status notification, after completion of the * delivery request. */ else { rcpt_stat = bounce_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); } return (rcpt_stat); }
static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr) { const char *myname = "deliver_mailbox_file"; char *spool_dir; char *mailbox; DSN_BUF *why = state.msg_attr.why; MBOX *mp; int mail_copy_status; int deliver_status; int copy_flags; VSTRING *biff; long end; struct stat st; uid_t spool_uid; gid_t spool_gid; uid_t chown_uid; gid_t chown_gid; /* * Make verbose logging easier to understand. */ state.level++; if (msg_verbose) MSG_LOG_STATE(myname, state); /* * Don't deliver trace-only requests. */ if (DEL_REQ_TRACE_ONLY(state.request->flags)) { dsb_simple(why, "2.0.0", "delivers to mailbox"); return (sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr))); } /* * Initialize. Assume the operation will fail. Set the delivered * attribute to reflect the final recipient. */ if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0) msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp)); if (var_frozen_delivered == 0) state.msg_attr.delivered = state.msg_attr.rcpt.address; mail_copy_status = MAIL_COPY_STAT_WRITE; if (*var_home_mailbox) { spool_dir = 0; mailbox = concatenate(usr_attr.home, "/", var_home_mailbox, (char *) 0); } else { spool_dir = var_mail_spool_dir; mailbox = concatenate(spool_dir, "/", state.msg_attr.user, (char *) 0); } /* * Mailbox delivery with least privilege. As long as we do not use root * privileges this code may also work over NFS. * * If delivering to the recipient's home directory, perform all operations * (including file locking) as that user (Mike Muuss, Army Research * Laboratory, USA). * * If delivering to the mail spool directory, and the spool directory is * world-writable, deliver as the recipient; if the spool directory is * group-writable, use the recipient user id and the mail spool group id. * * Otherwise, use root privileges and chown the mailbox. */ if (spool_dir == 0 || stat(spool_dir, &st) < 0 || (st.st_mode & S_IWOTH) != 0) { spool_uid = usr_attr.uid; spool_gid = usr_attr.gid; } else if ((st.st_mode & S_IWGRP) != 0) { spool_uid = usr_attr.uid; spool_gid = st.st_gid; } else { spool_uid = 0; spool_gid = 0; } if (spool_uid == usr_attr.uid) { chown_uid = -1; chown_gid = -1; } else { chown_uid = usr_attr.uid; chown_gid = usr_attr.gid; } if (msg_verbose) msg_info("spool_uid/gid %ld/%ld chown_uid/gid %ld/%ld", (long) spool_uid, (long) spool_gid, (long) chown_uid, (long) chown_gid); /* * Lock the mailbox and open/create the mailbox file. Depending on the * type of locking used, we lock first or we open first. * * Write the file as the recipient, so that file quota work. */ copy_flags = MAIL_COPY_MBOX; if ((local_deliver_hdr_mask & DELIVER_HDR_FILE) == 0) copy_flags &= ~MAIL_COPY_DELIVERED; set_eugid(spool_uid, spool_gid); mp = mbox_open(mailbox, O_APPEND | O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR, &st, chown_uid, chown_gid, local_mbox_lock_mask, "5.2.0", why); if (mp != 0) { if (spool_uid != usr_attr.uid || spool_gid != usr_attr.gid) set_eugid(usr_attr.uid, usr_attr.gid); if (S_ISREG(st.st_mode) == 0) { vstream_fclose(mp->fp); dsb_simple(why, "5.2.0", "destination %s is not a regular file", mailbox); } else if (var_strict_mbox_owner && st.st_uid != usr_attr.uid) { vstream_fclose(mp->fp); dsb_simple(why, "4.2.0", "destination %s is not owned by recipient", mailbox); msg_warn("specify \"%s = no\" to ignore mailbox ownership mismatch", VAR_STRICT_MBOX_OWNER); } else { end = vstream_fseek(mp->fp, (off_t) 0, SEEK_END); mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp, copy_flags, "\n", why); } if (spool_uid != usr_attr.uid || spool_gid != usr_attr.gid) set_eugid(spool_uid, spool_gid); mbox_release(mp); } set_eugid(var_owner_uid, var_owner_gid); /* * As the mail system, bounce, defer delivery, or report success. */ if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) { deliver_status = DEL_STAT_DEFER; } else if (mail_copy_status != 0) { vstring_sprintf_prepend(why->reason, "cannot update mailbox %s for user %s. ", mailbox, state.msg_attr.user); deliver_status = (STR(why->status)[0] == '4' ? defer_append : bounce_append) (BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); } else { dsb_simple(why, "2.0.0", "delivered to mailbox"); deliver_status = sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr)); if (var_biff) { biff = vstring_alloc(100); vstring_sprintf(biff, "%s@%ld", usr_attr.logname, (long) end); biff_notify(STR(biff), VSTRING_LEN(biff) + 1); vstring_free(biff); } } /* * Clean up. */ myfree(mailbox); return (deliver_status); }
int bounce_append_intern(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn) { DSN my_dsn = *dsn; int status; /* * MTA-requested address verification information is stored in the verify * service database. */ if (flags & DEL_REQ_FLAG_MTA_VRFY) { my_dsn.action = "undeliverable"; status = verify_append(id, stats, rcpt, relay, &my_dsn, DEL_RCPT_STAT_BOUNCE); return (status); } /* * User-requested address verification information is logged and mailed * to the requesting user. */ if (flags & DEL_REQ_FLAG_USR_VRFY) { my_dsn.action = "undeliverable"; status = trace_append(flags, id, stats, rcpt, relay, &my_dsn); return (status); } /* * Normal (well almost) delivery. When we're pretending that we can't * bounce, don't create a defer log file when we wouldn't keep the bounce * log file. That's a lot of negatives in one sentence. */ else if (var_soft_bounce && (flags & BOUNCE_FLAG_CLEAN)) { return (-1); } /* * Normal mail delivery. May also send a delivery record to the user. * * XXX DSN We write all recipients to the bounce logfile regardless of DSN * NOTIFY options, because those options don't apply to postmaster * notifications. */ else { char *my_status = mystrdup(my_dsn.status); const char *log_status = var_soft_bounce ? "SOFTBOUNCE" : "bounced"; /* * Supply default action. */ my_dsn.status = my_status; if (var_soft_bounce) { my_status[0] = '4'; my_dsn.action = "delayed"; } else { my_dsn.action = "failed"; } if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ? var_defer_service : var_bounce_service, ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn, ATTR_TYPE_END) == 0 && ((flags & DEL_REQ_FLAG_RECORD) == 0 || trace_append(flags, id, stats, rcpt, relay, &my_dsn) == 0)) { log_adhoc(id, stats, rcpt, relay, &my_dsn, log_status); status = (var_soft_bounce ? -1 : 0); } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) { VSTRING *junk = vstring_alloc(100); my_dsn.status = "4.3.0"; vstring_sprintf(junk, "%s or %s service failure", var_bounce_service, var_trace_service); my_dsn.reason = vstring_str(junk); status = defer_append_intern(flags, id, stats, rcpt, relay, &my_dsn); vstring_free(junk); } else { status = -1; } myfree(my_status); return (status); } }
int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) { const char *myname = "deliver_mailbox"; int status; struct mypasswd *mbox_pwd; char *path; static MAPS *transp_maps; const char *map_transport; static MAPS *cmd_maps; const char *map_command; /* * Make verbose logging easier to understand. */ state.level++; if (msg_verbose) MSG_LOG_STATE(myname, state); /* * DUPLICATE ELIMINATION * * Don't come here more than once, whether or not the recipient exists. */ if (been_here(state.dup_filter, "mailbox %s", state.msg_attr.local)) return (YES); /* * Delegate mailbox delivery to another message transport. */ if (*var_mbox_transp_maps && transp_maps == 0) transp_maps = maps_create(VAR_MBOX_TRANSP_MAPS, var_mbox_transp_maps, DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB); /* The -1 is a hint for the down-stream deliver_completed() function. */ if (*var_mbox_transp_maps && (map_transport = maps_find(transp_maps, state.msg_attr.user, DICT_FLAG_NONE)) != 0) { state.msg_attr.rcpt.offset = -1L; *statusp = deliver_pass(MAIL_CLASS_PRIVATE, map_transport, state.request, &state.msg_attr.rcpt); return (YES); } if (*var_mailbox_transport) { state.msg_attr.rcpt.offset = -1L; *statusp = deliver_pass(MAIL_CLASS_PRIVATE, var_mailbox_transport, state.request, &state.msg_attr.rcpt); return (YES); } /* * Skip delivery when this recipient does not exist. */ if ((mbox_pwd = mypwnam(state.msg_attr.user)) == 0) return (NO); /* * No early returns or we have a memory leak. */ /* * DELIVERY RIGHTS * * Use the rights of the recipient user. */ SET_USER_ATTR(usr_attr, mbox_pwd, state.level); /* * Deliver to mailbox, maildir or to external command. */ #define LAST_CHAR(s) (s[strlen(s) - 1]) if (*var_mailbox_cmd_maps && cmd_maps == 0) cmd_maps = maps_create(VAR_MAILBOX_CMD_MAPS, var_mailbox_cmd_maps, DICT_FLAG_LOCK | DICT_FLAG_PARANOID); if (*var_mailbox_cmd_maps && (map_command = maps_find(cmd_maps, state.msg_attr.user, DICT_FLAG_NONE)) != 0) { status = deliver_command(state, usr_attr, map_command); } else if (*var_mailbox_command) { status = deliver_command(state, usr_attr, var_mailbox_command); } else if (*var_home_mailbox && LAST_CHAR(var_home_mailbox) == '/') { path = concatenate(usr_attr.home, "/", var_home_mailbox, (char *) 0); status = deliver_maildir(state, usr_attr, path); myfree(path); } else if (*var_mail_spool_dir && LAST_CHAR(var_mail_spool_dir) == '/') { path = concatenate(var_mail_spool_dir, state.msg_attr.user, "/", (char *) 0); status = deliver_maildir(state, usr_attr, path); myfree(path); } else status = deliver_mailbox_file(state, usr_attr); /* * Cleanup. */ mypwfree(mbox_pwd); *statusp = status; return (YES); }
static void psc_dnsbl_add_site(const char *site) { const char *myname = "psc_dnsbl_add_site"; char *saved_site = mystrdup(site); VSTRING *byte_codes = 0; PSC_DNSBL_HEAD *head; PSC_DNSBL_SITE *new_site; char junk; const char *weight_text; char *pattern_text; int weight; HTABLE_INFO *ht; char *parse_err; /* * Parse the required DNSBL domain name, the optional reply filter and * the optional reply weight factor. */ #define DO_GRIPE 1 /* Negative weight means whitelist. */ if ((weight_text = split_at(saved_site, '*')) != 0) { if (sscanf(weight_text, "%d%c", &weight, &junk) != 1) msg_fatal("bad DNSBL weight factor \"%s\" in \"%s\"", weight_text, site); } else { weight = 1; } /* Reply filter. */ if ((pattern_text = split_at(saved_site, '=')) != 0) { byte_codes = vstring_alloc(100); if ((parse_err = ip_match_parse(byte_codes, pattern_text)) != 0) msg_fatal("bad DNSBL filter syntax: %s", parse_err); } if (valid_hostname(saved_site, DO_GRIPE) == 0) msg_fatal("bad DNSBL domain name \"%s\" in \"%s\"", saved_site, site); if (msg_verbose > 1) msg_info("%s: \"%s\" -> domain=\"%s\" pattern=\"%s\" weight=%d", myname, site, saved_site, pattern_text ? pattern_text : "null", weight); /* * Look up or create the (filter, weight) list head for this DNSBL domain * name. */ if ((head = (PSC_DNSBL_HEAD *) htable_find(dnsbl_site_cache, saved_site)) == 0) { head = (PSC_DNSBL_HEAD *) mymalloc(sizeof(*head)); ht = htable_enter(dnsbl_site_cache, saved_site, (char *) head); /* Translate the DNSBL name into a safe name if available. */ if (psc_dnsbl_reply == 0 || (head->safe_dnsbl = dict_get(psc_dnsbl_reply, saved_site)) == 0) head->safe_dnsbl = ht->key; if (psc_dnsbl_reply && psc_dnsbl_reply->error) msg_fatal("%s:%s lookup error", psc_dnsbl_reply->type, psc_dnsbl_reply->name); head->first = 0; } /* * Append the new (filter, weight) node to the list for this DNSBL domain * name. */ new_site = (PSC_DNSBL_SITE *) mymalloc(sizeof(*new_site)); new_site->filter = (pattern_text ? mystrdup(pattern_text) : 0); new_site->byte_codes = (byte_codes ? ip_match_save(byte_codes) : 0); new_site->weight = weight; new_site->next = head->first; head->first = new_site; myfree(saved_site); if (byte_codes) vstring_free(byte_codes); }
int cleanup_bounce(CLEANUP_STATE *state) { const char *myname = "cleanup_bounce"; VSTRING *buf = vstring_alloc(100); const CLEANUP_STAT_DETAIL *detail; DSN_SPLIT dp; const char *dsn_status; const char *dsn_text; char *rcpt = 0; RECIPIENT recipient; DSN dsn; char *attr_name; char *attr_value; char *dsn_orcpt = 0; int dsn_notify = 0; char *orig_rcpt = 0; char *start; int rec_type; int junk; long curr_offset; const char *encoding; const char *dsn_envid; int dsn_ret; int bounce_err; /* * Parse the failure reason if one was given, otherwise use a generic * mapping from cleanup-internal error code to (DSN + text). */ if (state->reason) { dsn_split(&dp, "5.0.0", state->reason); dsn_status = DSN_STATUS(dp.dsn); dsn_text = dp.text; } else { detail = cleanup_stat_detail(state->errs); dsn_status = detail->dsn; dsn_text = detail->text; } /* * Create a bounce logfile with one entry for each final recipient. * Degrade gracefully in case of no recipients or no queue file. * * Victor Duchovni observes that the number of recipients in the queue file * can potentially be very large due to virtual alias expansion. This can * expand the recipient count by virtual_alias_expansion_limit (default: * 1000) times. * * After a queue file write error, purge any unwritten data (so that * vstream_fseek() won't fail while trying to flush it) and reset the * stream error flags to avoid false alarms. */ if (vstream_ferror(state->dst) || vstream_fflush(state->dst)) { (void) vstream_fpurge(state->dst, VSTREAM_PURGE_BOTH); vstream_clearerr(state->dst); } if (vstream_fseek(state->dst, 0L, SEEK_SET) < 0) msg_fatal("%s: seek %s: %m", myname, cleanup_path); while ((state->errs & CLEANUP_STAT_WRITE) == 0) { if ((curr_offset = vstream_ftell(state->dst)) < 0) msg_fatal("%s: vstream_ftell %s: %m", myname, cleanup_path); if ((rec_type = rec_get(state->dst, buf, 0)) <= 0 || rec_type == REC_TYPE_END) break; start = STR(buf); if (rec_type == REC_TYPE_ATTR) { if (split_nameval(STR(buf), &attr_name, &attr_value) != 0 || *attr_value == 0) continue; /* Map attribute names to pseudo record type. */ if ((junk = rec_attr_map(attr_name)) != 0) { start = attr_value; rec_type = junk; } } switch (rec_type) { case REC_TYPE_DSN_ORCPT: /* RCPT TO ORCPT parameter */ if (dsn_orcpt != 0) /* can't happen */ myfree(dsn_orcpt); dsn_orcpt = mystrdup(start); break; case REC_TYPE_DSN_NOTIFY: /* RCPT TO NOTIFY parameter */ if (alldig(start) && (junk = atoi(start)) > 0 && DSN_NOTIFY_OK(junk)) dsn_notify = junk; else dsn_notify = 0; break; case REC_TYPE_ORCP: /* unmodified RCPT TO address */ if (orig_rcpt != 0) /* can't happen */ myfree(orig_rcpt); orig_rcpt = mystrdup(start); break; case REC_TYPE_RCPT: /* rewritten RCPT TO address */ rcpt = start; RECIPIENT_ASSIGN(&recipient, curr_offset, dsn_orcpt ? dsn_orcpt : "", dsn_notify, orig_rcpt ? orig_rcpt : rcpt, rcpt); (void) DSN_SIMPLE(&dsn, dsn_status, dsn_text); cleanup_bounce_append(state, &recipient, &dsn); /* FALLTHROUGH */ case REC_TYPE_DRCP: /* canceled recipient */ case REC_TYPE_DONE: /* can't happen */ if (orig_rcpt != 0) { myfree(orig_rcpt); orig_rcpt = 0; } if (dsn_orcpt != 0) { myfree(dsn_orcpt); dsn_orcpt = 0; } dsn_notify = 0; break; } } if (orig_rcpt != 0) /* can't happen */ myfree(orig_rcpt); if (dsn_orcpt != 0) /* can't happen */ myfree(dsn_orcpt); /* * No recipients. Yes, this can happen. */ if ((state->errs & CLEANUP_STAT_WRITE) == 0 && rcpt == 0) { RECIPIENT_ASSIGN(&recipient, 0, "", 0, "", "unknown"); (void) DSN_SIMPLE(&dsn, dsn_status, dsn_text); cleanup_bounce_append(state, &recipient, &dsn); } vstring_free(buf); /* * Flush the bounce logfile to the sender. See also qmgr_active.c. */ if ((state->errs & CLEANUP_STAT_WRITE) == 0) { if ((encoding = nvtable_find(state->attr, MAIL_ATTR_ENCODING)) == 0) encoding = MAIL_ATTR_ENC_NONE; dsn_envid = state->dsn_envid ? state->dsn_envid : ""; /* Do not send unfiltered (body) content. */ dsn_ret = (state->errs & (CLEANUP_STAT_CONT | CLEANUP_STAT_SIZE)) ? DSN_RET_HDRS : state->dsn_ret; if (state->verp_delims == 0 || var_verp_bounce_off) { bounce_err = bounce_flush(BOUNCE_FLAG_CLEAN, state->queue_name, state->queue_id, encoding, state->smtputf8, state->sender, dsn_envid, dsn_ret); } else { bounce_err = bounce_flush_verp(BOUNCE_FLAG_CLEAN, state->queue_name, state->queue_id, encoding, state->smtputf8, state->sender, dsn_envid, dsn_ret, state->verp_delims); } if (bounce_err != 0) { msg_warn("%s: bounce message failure", state->queue_id); state->errs |= CLEANUP_STAT_WRITE; } } /* * Schedule this message (and trace logfile) for deletion when all is * well. When all is not well these files would be deleted too, but the * client would get a different completion status so we have to carefully * maintain the bits anyway. */ if ((state->errs &= CLEANUP_STAT_WRITE) == 0) state->flags |= CLEANUP_FLAG_DISCARD; return (state->errs); }
static void enqueue(const int flags, const char *encoding, const char *dsn_envid, int dsn_ret, int dsn_notify, const char *rewrite_context, const char *sender, const char *full_name, char **recipients) { VSTRING *buf; VSTREAM *dst; char *saved_sender; char **cpp; int type; char *start; int skip_from_; TOK822 *tree; TOK822 *tp; int rcpt_count = 0; enum { STRIP_CR_DUNNO, STRIP_CR_DO, STRIP_CR_DONT, STRIP_CR_ERROR } strip_cr; MAIL_STREAM *handle; VSTRING *postdrop_command; uid_t uid = getuid(); int status; int naddr; int prev_type; MIME_STATE *mime_state = 0; SM_STATE state; int mime_errs; const char *errstr; int addr_count; int level; static NAME_CODE sm_fix_eol_table[] = { SM_FIX_EOL_ALWAYS, STRIP_CR_DO, SM_FIX_EOL_STRICT, STRIP_CR_DUNNO, SM_FIX_EOL_NEVER, STRIP_CR_DONT, 0, STRIP_CR_ERROR, }; /* * Access control is enforced in the postdrop command. The code here * merely produces a more user-friendly interface. */ if ((errstr = check_user_acl_byuid(var_submit_acl, uid)) != 0) msg_fatal_status(EX_NOPERM, "User %s(%ld) is not allowed to submit mail", errstr, (long) uid); /* * Initialize. */ buf = vstring_alloc(100); /* * Stop run-away process accidents by limiting the queue file size. This * is not a defense against DOS attack. */ if (var_message_limit > 0 && get_file_limit() > var_message_limit) set_file_limit((off_t) var_message_limit); /* * The sender name is provided by the user. In principle, the mail pickup * service could deduce the sender name from queue file ownership, but: * pickup would not be able to run chrooted, and it may not be desirable * to use login names at all. */ if (sender != 0) { VSTRING_RESET(buf); VSTRING_TERMINATE(buf); tree = tok822_parse(sender); for (naddr = 0, tp = tree; tp != 0; tp = tp->next) if (tp->type == TOK822_ADDR && naddr++ == 0) tok822_internalize(buf, tp->head, TOK822_STR_DEFL); tok822_free_tree(tree); saved_sender = mystrdup(STR(buf)); if (naddr > 1) msg_warn("-f option specified malformed sender: %s", sender); } else { if ((sender = username()) == 0) msg_fatal_status(EX_OSERR, "no login name found for user ID %lu", (unsigned long) uid); saved_sender = mystrdup(sender); } /* * Let the postdrop command open the queue file for us, and sanity check * the content. XXX Make postdrop a manifest constant. */ errno = 0; postdrop_command = vstring_alloc(1000); vstring_sprintf(postdrop_command, "%s/postdrop -r", var_command_dir); for (level = 0; level < msg_verbose; level++) vstring_strcat(postdrop_command, " -v"); if ((handle = mail_stream_command(STR(postdrop_command))) == 0) msg_fatal_status(EX_UNAVAILABLE, "%s(%ld): unable to execute %s: %m", saved_sender, (long) uid, STR(postdrop_command)); vstring_free(postdrop_command); dst = handle->stream; /* * First, write envelope information to the output stream. * * For sendmail compatibility, parse each command-line recipient as if it * were an RFC 822 message header; some MUAs specify comma-separated * recipient lists; and some MUAs even specify "word word <address>". * * Sort-uniq-ing the recipient list is done after address canonicalization, * before recipients are written to queue file. That's cleaner than * having the queue manager nuke duplicate recipient status records. * * XXX Should limit the size of envelope records. * * With "sendmail -N", instead of a per-message NOTIFY record we store one * per recipient so that we can simplify the implementation somewhat. */ if (dsn_envid) rec_fprintf(dst, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_DSN_ENVID, dsn_envid); if (dsn_ret) rec_fprintf(dst, REC_TYPE_ATTR, "%s=%d", MAIL_ATTR_DSN_RET, dsn_ret); rec_fprintf(dst, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_RWR_CONTEXT, rewrite_context); if (full_name || (full_name = fullname()) != 0) rec_fputs(dst, REC_TYPE_FULL, full_name); rec_fputs(dst, REC_TYPE_FROM, saved_sender); if (verp_delims && *saved_sender == 0) msg_fatal_status(EX_USAGE, "%s(%ld): -V option requires non-null sender address", saved_sender, (long) uid); if (encoding) rec_fprintf(dst, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ENCODING, encoding); if (DEL_REQ_TRACE_FLAGS(flags)) rec_fprintf(dst, REC_TYPE_ATTR, "%s=%d", MAIL_ATTR_TRACE_FLAGS, DEL_REQ_TRACE_FLAGS(flags)); if (verp_delims) rec_fputs(dst, REC_TYPE_VERP, verp_delims); if (recipients) { for (cpp = recipients; *cpp != 0; cpp++) { tree = tok822_parse(*cpp); for (addr_count = 0, tp = tree; tp != 0; tp = tp->next) { if (tp->type == TOK822_ADDR) { tok822_internalize(buf, tp->head, TOK822_STR_DEFL); if (dsn_notify) rec_fprintf(dst, REC_TYPE_ATTR, "%s=%d", MAIL_ATTR_DSN_NOTIFY, dsn_notify); if (REC_PUT_BUF(dst, REC_TYPE_RCPT, buf) < 0) msg_fatal_status(EX_TEMPFAIL, "%s(%ld): error writing queue file: %m", saved_sender, (long) uid); ++rcpt_count; ++addr_count; } } tok822_free_tree(tree); if (addr_count == 0) { if (rec_put(dst, REC_TYPE_RCPT, "", 0) < 0) msg_fatal_status(EX_TEMPFAIL, "%s(%ld): error writing queue file: %m", saved_sender, (long) uid); ++rcpt_count; } } } /* * Append the message contents to the queue file. Write chunks of at most * 1kbyte. Internally, we use different record types for data ending in * LF and for data that doesn't, so we can actually be binary transparent * for local mail. Unfortunately, SMTP has no record continuation * convention, so there is no guarantee that arbitrary data will be * delivered intact via SMTP. Strip leading From_ lines. For the benefit * of UUCP environments, also get rid of leading >>>From_ lines. */ rec_fputs(dst, REC_TYPE_MESG, ""); if (DEL_REQ_TRACE_ONLY(flags) != 0) { if (flags & SM_FLAG_XRCPT) msg_fatal_status(EX_USAGE, "%s(%ld): -t option cannot be used with -bv", saved_sender, (long) uid); if (*saved_sender) rec_fprintf(dst, REC_TYPE_NORM, "From: %s", saved_sender); rec_fprintf(dst, REC_TYPE_NORM, "Subject: probe"); if (recipients) { rec_fprintf(dst, REC_TYPE_CONT, "To:"); for (cpp = recipients; *cpp != 0; cpp++) { rec_fprintf(dst, REC_TYPE_NORM, " %s%s", *cpp, cpp[1] ? "," : ""); } } } else { /* * Initialize the MIME processor and set up the callback context. */ if (flags & SM_FLAG_XRCPT) { state.dst = dst; state.recipients = argv_alloc(2); state.resent_recip = argv_alloc(2); state.resent = 0; state.saved_sender = saved_sender; state.uid = uid; state.temp = vstring_alloc(10); mime_state = mime_state_alloc(MIME_OPT_DISABLE_MIME | MIME_OPT_REPORT_TRUNC_HEADER, output_header, (MIME_STATE_ANY_END) 0, output_text, (MIME_STATE_ANY_END) 0, (MIME_STATE_ERR_PRINT) 0, (void *) &state); } /* * Process header/body lines. */ skip_from_ = 1; strip_cr = name_code(sm_fix_eol_table, NAME_CODE_FLAG_STRICT_CASE, var_sm_fix_eol); if (strip_cr == STRIP_CR_ERROR) msg_fatal_status(EX_USAGE, "invalid %s value: %s", VAR_SM_FIX_EOL, var_sm_fix_eol); for (prev_type = 0; (type = rec_streamlf_get(VSTREAM_IN, buf, var_line_limit)) != REC_TYPE_EOF; prev_type = type) { if (strip_cr == STRIP_CR_DUNNO && type == REC_TYPE_NORM) { if (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r') strip_cr = STRIP_CR_DO; else strip_cr = STRIP_CR_DONT; } if (skip_from_) { if (type == REC_TYPE_NORM) { start = STR(buf); if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) continue; } skip_from_ = 0; } if (strip_cr == STRIP_CR_DO && type == REC_TYPE_NORM) while (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r') vstring_truncate(buf, VSTRING_LEN(buf) - 1); if ((flags & SM_FLAG_AEOF) && prev_type != REC_TYPE_CONT && VSTRING_LEN(buf) == 1 && *STR(buf) == '.') break; if (mime_state) { mime_errs = mime_state_update(mime_state, type, STR(buf), VSTRING_LEN(buf)); if (mime_errs) msg_fatal_status(EX_DATAERR, "%s(%ld): unable to extract recipients: %s", saved_sender, (long) uid, mime_state_error(mime_errs)); } else { if (REC_PUT_BUF(dst, type, buf) < 0) msg_fatal_status(EX_TEMPFAIL, "%s(%ld): error writing queue file: %m", saved_sender, (long) uid); } } } /* * Finish MIME processing. We need a final mime_state_update() call in * order to flush text that is still buffered. That can happen when the * last line did not end in newline. */ if (mime_state) { mime_errs = mime_state_update(mime_state, REC_TYPE_EOF, "", 0); if (mime_errs) msg_fatal_status(EX_DATAERR, "%s(%ld): unable to extract recipients: %s", saved_sender, (long) uid, mime_state_error(mime_errs)); mime_state = mime_state_free(mime_state); } /* * Append recipient addresses that were extracted from message headers. */ rec_fputs(dst, REC_TYPE_XTRA, ""); if (flags & SM_FLAG_XRCPT) { for (cpp = state.resent ? state.resent_recip->argv : state.recipients->argv; *cpp; cpp++) { if (dsn_notify) rec_fprintf(dst, REC_TYPE_ATTR, "%s=%d", MAIL_ATTR_DSN_NOTIFY, dsn_notify); if (rec_put(dst, REC_TYPE_RCPT, *cpp, strlen(*cpp)) < 0) msg_fatal_status(EX_TEMPFAIL, "%s(%ld): error writing queue file: %m", saved_sender, (long) uid); ++rcpt_count; } argv_free(state.recipients); argv_free(state.resent_recip); vstring_free(state.temp); } if (rcpt_count == 0) msg_fatal_status(EX_USAGE, (flags & SM_FLAG_XRCPT) ? "%s(%ld): No recipient addresses found in message header" : "Recipient addresses must be specified on" " the command line or via the -t option", saved_sender, (long) uid); /* * Identify the end of the queue file. */ rec_fputs(dst, REC_TYPE_END, ""); /* * Make sure that the message makes it to the file system. Once we have * terminated with successful exit status we cannot lose the message due * to "frivolous reasons". If all goes well, prevent the run-time error * handler from removing the file. */ if (vstream_ferror(VSTREAM_IN)) msg_fatal_status(EX_DATAERR, "%s(%ld): error reading input: %m", saved_sender, (long) uid); if ((status = mail_stream_finish(handle, (VSTRING *) 0)) != 0) msg_fatal_status((status & CLEANUP_STAT_BAD) ? EX_SOFTWARE : (status & CLEANUP_STAT_WRITE) ? EX_TEMPFAIL : EX_UNAVAILABLE, "%s(%ld): %s", saved_sender, (long) uid, cleanup_strerror(status)); /* * Don't leave them in the dark. */ if (DEL_REQ_TRACE_FLAGS(flags)) { vstream_printf("Mail Delivery Status Report will be mailed to <%s>.\n", saved_sender); vstream_fflush(VSTREAM_OUT); } /* * Cleanup. Not really necessary as we're about to exit, but good for * debugging purposes. */ vstring_free(buf); myfree(saved_sender); }
void i_mmarray_dst(i_mmarray *ar) { ar->lines=0; if (ar->data != NULL) { myfree(ar->data); ar->data=NULL; } }
int main(int argc, char **argv) { static char *full_name = 0; /* sendmail -F */ struct stat st; char *slash; char *sender = 0; /* sendmail -f */ int c; int fd; int mode; ARGV *ext_argv; int debug_me = 0; int err; int n; int flags = SM_FLAG_DEFAULT; char *site_to_flush = 0; char *id_to_flush = 0; char *encoding = 0; char *qtime = 0; const char *errstr; uid_t uid; const char *rewrite_context = MAIL_ATTR_RWR_LOCAL; int dsn_notify = 0; int dsn_ret = 0; const char *dsn_envid = 0; int saved_optind; /* * Fingerprint executables and core dumps. */ MAIL_VERSION_STAMP_ALLOCATE; /* * Be consistent with file permissions. */ umask(022); /* * To minimize confusion, make sure that the standard file descriptors * are open before opening anything else. XXX Work around for 44BSD where * fstat can return EBADF on an open file descriptor. */ for (fd = 0; fd < 3; fd++) if (fstat(fd, &st) == -1 && (close(fd), open("/dev/null", O_RDWR, 0)) != fd) msg_fatal_status(EX_OSERR, "open /dev/null: %m"); /* * The CDE desktop calendar manager leaks a parent file descriptor into * the child process. For the sake of sendmail compatibility we have to * close the file descriptor otherwise mail notification will hang. */ for ( /* void */ ; fd < 100; fd++) (void) close(fd); /* * Process environment options as early as we can. We might be called * from a set-uid (set-gid) program, so be careful with importing * environment variables. */ if (safe_getenv(CONF_ENV_VERB)) msg_verbose = 1; if (safe_getenv(CONF_ENV_DEBUG)) debug_me = 1; /* * Initialize. Set up logging, read the global configuration file and * extract configuration information. Set up signal handlers so that we * can clean up incomplete output. */ if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; msg_vstream_init(argv[0], VSTREAM_ERR); msg_cleanup(tempfail); msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* * Check the Postfix library version as soon as we enable logging. */ MAIL_VERSION_CHECK; /* * Some sites mistakenly install Postfix sendmail as set-uid root. Drop * set-uid privileges only when root, otherwise some systems will not * reset the saved set-userid, which would be a security vulnerability. */ if (geteuid() == 0 && getuid() != 0) { msg_warn("the Postfix sendmail command has set-uid root file permissions"); msg_warn("or the command is run from a set-uid root process"); msg_warn("the Postfix sendmail command must be installed without set-uid root file permissions"); set_ugid(getuid(), getgid()); } /* * Further initialization. Load main.cf first, so that command-line * options can override main.cf settings. Pre-scan the argument list so * that we load the right main.cf file. */ #define GETOPT_LIST "A:B:C:F:GIL:N:O:R:UV:X:b:ce:f:h:imno:p:r:q:tvx" saved_optind = optind; while (argv[OPTIND] != 0) { if (strcmp(argv[OPTIND], "-q") == 0) { /* not getopt compatible */ optind++; continue; } if ((c = GETOPT(argc, argv, GETOPT_LIST)) <= 0) break; if (c == 'C') { VSTRING *buf = vstring_alloc(1); if (setenv(CONF_ENV_PATH, strcmp(sane_basename(buf, optarg), MAIN_CONF_FILE) == 0 ? sane_dirname(buf, optarg) : optarg, 1) < 0) msg_fatal_status(EX_UNAVAILABLE, "out of memory"); vstring_free(buf); } } optind = saved_optind; mail_conf_read(); if (strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0) msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY); get_mail_conf_str_table(str_table); if (chdir(var_queue_dir)) msg_fatal_status(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir); signal(SIGPIPE, SIG_IGN); /* * Optionally start the debugger on ourself. This must be done after * reading the global configuration file, because that file specifies * what debugger command to execute. */ if (debug_me) debug_process(); /* * The default mode of operation is determined by the process name. It * can, however, be changed via command-line options (for example, * "newaliases -bp" will show the mail queue). */ if (strcmp(argv[0], "mailq") == 0) { mode = SM_MODE_MAILQ; } else if (strcmp(argv[0], "newaliases") == 0) { mode = SM_MODE_NEWALIAS; } else if (strcmp(argv[0], "smtpd") == 0) { mode = SM_MODE_DAEMON; } else { mode = SM_MODE_ENQUEUE; } /* * Parse JCL. Sendmail has been around for a long time, and has acquired * a large number of options in the course of time. Some options such as * -q are not parsable with GETOPT() and get special treatment. */ #define OPTIND (optind > 0 ? optind : 1) while (argv[OPTIND] != 0) { if (strcmp(argv[OPTIND], "-q") == 0) { if (mode == SM_MODE_DAEMON) msg_warn("ignoring -q option in daemon mode"); else mode = SM_MODE_FLUSHQ; optind++; continue; } if (strcmp(argv[OPTIND], "-V") == 0 && argv[OPTIND + 1] != 0 && strlen(argv[OPTIND + 1]) == 2) { msg_warn("option -V is deprecated with Postfix 2.3; " "specify -XV instead"); argv[OPTIND] = "-XV"; } if (strncmp(argv[OPTIND], "-V", 2) == 0 && strlen(argv[OPTIND]) == 4) { msg_warn("option %s is deprecated with Postfix 2.3; " "specify -X%s instead", argv[OPTIND], argv[OPTIND] + 1); argv[OPTIND] = concatenate("-X", argv[OPTIND] + 1, (char *) 0); } if (strcmp(argv[OPTIND], "-XV") == 0) { verp_delims = var_verp_delims; optind++; continue; } if ((c = GETOPT(argc, argv, GETOPT_LIST)) <= 0) break; switch (c) { default: if (msg_verbose) msg_info("-%c option ignored", c); break; case 'n': msg_fatal_status(EX_USAGE, "-%c option not supported", c); case 'B': if (strcmp(optarg, "8BITMIME") == 0)/* RFC 1652 */ encoding = MAIL_ATTR_ENC_8BIT; else if (strcmp(optarg, "7BIT") == 0) /* RFC 1652 */ encoding = MAIL_ATTR_ENC_7BIT; else msg_fatal_status(EX_USAGE, "-B option needs 8BITMIME or 7BIT"); break; case 'F': /* full name */ full_name = optarg; break; case 'G': /* gateway submission */ rewrite_context = MAIL_ATTR_RWR_REMOTE; break; case 'I': /* newaliases */ mode = SM_MODE_NEWALIAS; break; case 'N': if ((dsn_notify = dsn_notify_mask(optarg)) == 0) msg_warn("bad -N option value -- ignored"); break; case 'R': if ((dsn_ret = dsn_ret_code(optarg)) == 0) msg_warn("bad -R option value -- ignored"); break; case 'V': /* DSN, was: VERP */ if (strlen(optarg) > 100) msg_warn("too long -V option value -- ignored"); else if (!allprint(optarg)) msg_warn("bad syntax in -V option value -- ignored"); else dsn_envid = optarg; break; case 'X': switch (*optarg) { default: msg_fatal_status(EX_USAGE, "unsupported: -%c%c", c, *optarg); case 'V': /* VERP */ if (verp_delims_verify(optarg + 1) != 0) msg_fatal_status(EX_USAGE, "-V requires two characters from %s", var_verp_filter); verp_delims = optarg + 1; break; } break; case 'b': switch (*optarg) { default: msg_fatal_status(EX_USAGE, "unsupported: -%c%c", c, *optarg); case 'd': /* daemon mode */ case 'l': /* daemon mode */ if (mode == SM_MODE_FLUSHQ) msg_warn("ignoring -q option in daemon mode"); mode = SM_MODE_DAEMON; break; case 'h': /* print host status */ case 'H': /* flush host status */ mode = SM_MODE_IGNORE; break; case 'i': /* newaliases */ mode = SM_MODE_NEWALIAS; break; case 'm': /* deliver mail */ mode = SM_MODE_ENQUEUE; break; case 'p': /* mailq */ mode = SM_MODE_MAILQ; break; case 's': /* stand-alone mode */ mode = SM_MODE_USER; break; case 'v': /* expand recipients */ flags |= DEL_REQ_FLAG_USR_VRFY; break; } break; case 'f': sender = optarg; break; case 'i': flags &= ~SM_FLAG_AEOF; break; case 'o': switch (*optarg) { default: if (msg_verbose) msg_info("-%c%c option ignored", c, *optarg); break; case 'A': if (optarg[1] == 0) msg_fatal_status(EX_USAGE, "-oA requires pathname"); myfree(var_alias_db_map); var_alias_db_map = mystrdup(optarg + 1); set_mail_conf_str(VAR_ALIAS_DB_MAP, var_alias_db_map); break; case '7': case '8': break; case 'i': flags &= ~SM_FLAG_AEOF; break; case 'm': break; } break; case 'r': /* obsoleted by -f */ sender = optarg; break; case 'q': if (ISDIGIT(optarg[0])) { qtime = optarg; } else if (optarg[0] == 'R') { site_to_flush = optarg + 1; if (*site_to_flush == 0) msg_fatal_status(EX_USAGE, "specify: -qRsitename"); } else if (optarg[0] == 'I') { id_to_flush = optarg + 1; if (*id_to_flush == 0) msg_fatal_status(EX_USAGE, "specify: -qIqueueid"); } else { msg_fatal_status(EX_USAGE, "-q%c is not implemented", optarg[0]); } break; case 't': flags |= SM_FLAG_XRCPT; break; case 'v': msg_verbose++; break; case '?': msg_fatal_status(EX_USAGE, "usage: %s [options]", argv[0]); } } /* * Look for conflicting options and arguments. */ if ((flags & SM_FLAG_XRCPT) && mode != SM_MODE_ENQUEUE) msg_fatal_status(EX_USAGE, "-t can be used only in delivery mode"); if (site_to_flush && mode != SM_MODE_ENQUEUE) msg_fatal_status(EX_USAGE, "-qR can be used only in delivery mode"); if (id_to_flush && mode != SM_MODE_ENQUEUE) msg_fatal_status(EX_USAGE, "-qI can be used only in delivery mode"); if (flags & DEL_REQ_FLAG_USR_VRFY) { if (flags & SM_FLAG_XRCPT) msg_fatal_status(EX_USAGE, "-t option cannot be used with -bv"); if (dsn_notify) msg_fatal_status(EX_USAGE, "-N option cannot be used with -bv"); if (dsn_ret) msg_fatal_status(EX_USAGE, "-R option cannot be used with -bv"); if (msg_verbose == 1) msg_fatal_status(EX_USAGE, "-v option cannot be used with -bv"); } /* * The -v option plays double duty. One requests verbose delivery, more * than one requests verbose logging. */ if (msg_verbose == 1 && mode == SM_MODE_ENQUEUE) { msg_verbose = 0; flags |= DEL_REQ_FLAG_RECORD; } /* * Start processing. Everything is delegated to external commands. */ if (qtime && mode != SM_MODE_DAEMON) exit(0); switch (mode) { default: msg_panic("unknown operation mode: %d", mode); /* NOTREACHED */ case SM_MODE_ENQUEUE: if (site_to_flush) { if (argv[OPTIND]) msg_fatal_status(EX_USAGE, "flush site requires no recipient"); ext_argv = argv_alloc(2); argv_add(ext_argv, "postqueue", "-s", site_to_flush, (char *) 0); for (n = 0; n < msg_verbose; n++) argv_add(ext_argv, "-v", (char *) 0); argv_terminate(ext_argv); mail_run_replace(var_command_dir, ext_argv->argv); /* NOTREACHED */ } else if (id_to_flush) { if (argv[OPTIND]) msg_fatal_status(EX_USAGE, "flush queue_id requires no recipient"); ext_argv = argv_alloc(2); argv_add(ext_argv, "postqueue", "-i", id_to_flush, (char *) 0); for (n = 0; n < msg_verbose; n++) argv_add(ext_argv, "-v", (char *) 0); argv_terminate(ext_argv); mail_run_replace(var_command_dir, ext_argv->argv); /* NOTREACHED */ } else { enqueue(flags, encoding, dsn_envid, dsn_ret, dsn_notify, rewrite_context, sender, full_name, argv + OPTIND); exit(0); /* NOTREACHED */ } break; case SM_MODE_MAILQ: if (argv[OPTIND]) msg_fatal_status(EX_USAGE, "display queue mode requires no recipient"); ext_argv = argv_alloc(2); argv_add(ext_argv, "postqueue", "-p", (char *) 0); for (n = 0; n < msg_verbose; n++) argv_add(ext_argv, "-v", (char *) 0); argv_terminate(ext_argv); mail_run_replace(var_command_dir, ext_argv->argv); /* NOTREACHED */ case SM_MODE_FLUSHQ: if (argv[OPTIND]) msg_fatal_status(EX_USAGE, "flush queue mode requires no recipient"); ext_argv = argv_alloc(2); argv_add(ext_argv, "postqueue", "-f", (char *) 0); for (n = 0; n < msg_verbose; n++) argv_add(ext_argv, "-v", (char *) 0); argv_terminate(ext_argv); mail_run_replace(var_command_dir, ext_argv->argv); /* NOTREACHED */ case SM_MODE_DAEMON: if (argv[OPTIND]) msg_fatal_status(EX_USAGE, "daemon mode requires no recipient"); ext_argv = argv_alloc(2); argv_add(ext_argv, "postfix", (char *) 0); for (n = 0; n < msg_verbose; n++) argv_add(ext_argv, "-v", (char *) 0); argv_add(ext_argv, "start", (char *) 0); argv_terminate(ext_argv); err = (mail_run_background(var_command_dir, ext_argv->argv) < 0); argv_free(ext_argv); exit(err); break; case SM_MODE_NEWALIAS: if (argv[OPTIND]) msg_fatal_status(EX_USAGE, "alias initialization mode requires no recipient"); if (*var_alias_db_map == 0) return (0); ext_argv = argv_alloc(2); argv_add(ext_argv, "postalias", (char *) 0); for (n = 0; n < msg_verbose; n++) argv_add(ext_argv, "-v", (char *) 0); argv_split_append(ext_argv, var_alias_db_map, ", \t\r\n"); argv_terminate(ext_argv); mail_run_replace(var_command_dir, ext_argv->argv); /* NOTREACHED */ case SM_MODE_USER: if (argv[OPTIND]) msg_fatal_status(EX_USAGE, "stand-alone mode requires no recipient"); /* The actual enforcement happens in the postdrop command. */ if ((errstr = check_user_acl_byuid(var_submit_acl, uid = getuid())) != 0) msg_fatal_status(EX_NOPERM, "User %s(%ld) is not allowed to submit mail", errstr, (long) uid); ext_argv = argv_alloc(2); argv_add(ext_argv, "smtpd", "-S", (char *) 0); for (n = 0; n < msg_verbose; n++) argv_add(ext_argv, "-v", (char *) 0); argv_terminate(ext_argv); mail_run_replace(var_daemon_dir, ext_argv->argv); /* NOTREACHED */ case SM_MODE_IGNORE: exit(0); /* NOTREACHED */ } }
int match_hostaddr(MATCH_LIST *list, const char *addr, const char *pattern) { const char *myname = "match_hostaddr"; char *saved_patt; CIDR_MATCH match_info; DICT *dict; VSTRING *err; int rc; if (msg_verbose) msg_info("%s: %s ~? %s", myname, addr, pattern); #define V4_ADDR_STRING_CHARS "01234567890." #define V6_ADDR_STRING_CHARS V4_ADDR_STRING_CHARS "abcdefABCDEF:" if (addr[strspn(addr, V6_ADDR_STRING_CHARS)] != 0) return (0); /* * Try dictionary lookup. This can be case insensitive. */ if (MATCH_DICTIONARY(pattern)) { if ((dict = dict_handle(pattern)) == 0) msg_panic("%s: unknown dictionary: %s", myname, pattern); if (dict_get(dict, addr) != 0) return (1); if ((list->error = dict->error) != 0) return (match_error(list, "%s:%s: table lookup problem", dict->type, dict->name)); return (0); } /* * Try an exact match with the host address. */ if (pattern[0] != '[') { if (strcasecmp(addr, pattern) == 0) return (1); } else { size_t addr_len = strlen(addr); if (strncasecmp(addr, pattern + 1, addr_len) == 0 && strcmp(pattern + 1 + addr_len, "]") == 0) return (1); } /* * Light-weight tests before we get into expensive operations. * * - Don't bother matching IPv4 against IPv6. Postfix transforms * IPv4-in-IPv6 to native IPv4 form when IPv4 support is enabled in * Postfix; if not, then Postfix has no business dealing with IPv4 * addresses anyway. * * - Don't bother unless the pattern is either an IPv6 address or net/mask. * * We can safely skip IPv4 address patterns because their form is * unambiguous and they did not match in the strcasecmp() calls above. * * XXX We MUST skip (parent) domain names, which may appear in NAMADR_LIST * input, to avoid triggering false cidr_match_parse() errors. * * The last two conditions below are for backwards compatibility with * earlier Postfix versions: don't abort with fatal errors on junk that * was silently ignored (principle of least astonishment). */ if (!strchr(addr, ':') != !strchr(pattern, ':') || pattern[strcspn(pattern, ":/")] == 0 || pattern[strspn(pattern, V4_ADDR_STRING_CHARS)] == 0 || pattern[strspn(pattern, V6_ADDR_STRING_CHARS "[]/")] != 0) return (0); /* * No escape from expensive operations: either we have a net/mask * pattern, or we have an address that can have multiple valid * representations (e.g., 0:0:0:0:0:0:0:1 versus ::1, etc.). The only way * to find out if the address matches the pattern is to transform * everything into to binary form, and to do the comparison there. */ saved_patt = mystrdup(pattern); err = cidr_match_parse(&match_info, saved_patt, (VSTRING *) 0); myfree(saved_patt); if (err != 0) { list->error = DICT_ERR_RETRY; rc = match_error(list, "%s", vstring_str(err)); vstring_free(err); return (rc); } return (cidr_match_execute(&match_info, addr) != 0); }
int attr_vprint_plain(VSTREAM *fp, int flags, va_list ap) { const char *myname = "attr_print_plain"; int attr_type; char *attr_name; unsigned int_val; unsigned long long_val; char *str_val; HTABLE_INFO **ht_info_list; HTABLE_INFO **ht; static VSTRING *base64_buf; ssize_t len_val; ATTR_PRINT_SLAVE_FN print_fn; void *print_arg; /* * Sanity check. */ if (flags & ~ATTR_FLAG_ALL) msg_panic("%s: bad flags: 0x%x", myname, flags); /* * Iterate over all (type, name, value) triples, and produce output on * the fly. */ while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) { switch (attr_type) { case ATTR_TYPE_INT: attr_name = va_arg(ap, char *); int_val = va_arg(ap, int); vstream_fprintf(fp, "%s=%u\n", attr_name, (unsigned) int_val); if (msg_verbose) msg_info("send attr %s = %u", attr_name, (unsigned) int_val); break; case ATTR_TYPE_LONG: attr_name = va_arg(ap, char *); long_val = va_arg(ap, long); vstream_fprintf(fp, "%s=%lu\n", attr_name, long_val); if (msg_verbose) msg_info("send attr %s = %lu", attr_name, long_val); break; case ATTR_TYPE_STR: attr_name = va_arg(ap, char *); str_val = va_arg(ap, char *); vstream_fprintf(fp, "%s=%s\n", attr_name, str_val); if (msg_verbose) msg_info("send attr %s = %s", attr_name, str_val); break; case ATTR_TYPE_DATA: attr_name = va_arg(ap, char *); len_val = va_arg(ap, ssize_t); str_val = va_arg(ap, char *); if (base64_buf == 0) base64_buf = vstring_alloc(10); base64_encode(base64_buf, str_val, len_val); vstream_fprintf(fp, "%s=%s\n", attr_name, STR(base64_buf)); if (msg_verbose) msg_info("send attr %s = [data %ld bytes]", attr_name, (long) len_val); break; case ATTR_TYPE_FUNC: print_fn = va_arg(ap, ATTR_PRINT_SLAVE_FN); print_arg = va_arg(ap, void *); print_fn(attr_print_plain, fp, flags | ATTR_FLAG_MORE, print_arg); break; case ATTR_TYPE_HASH: ht_info_list = htable_list(va_arg(ap, HTABLE *)); for (ht = ht_info_list; *ht; ht++) { vstream_fprintf(fp, "%s=%s\n", ht[0]->key, ht[0]->value); if (msg_verbose) msg_info("send attr name %s value %s", ht[0]->key, ht[0]->value); } myfree((char *) ht_info_list); break; default: msg_panic("%s: unknown type code: %d", myname, attr_type); } } if ((flags & ATTR_FLAG_MORE) == 0) VSTREAM_PUTC('\n', fp); return (vstream_ferror(fp)); }
void fset_master_ent(char *path) { if (master_path != 0) myfree(master_path); master_path = mystrdup(path); }
void parse(void) { char *s,*line,*inst; char *ext[MAX_QUALIFIERS?MAX_QUALIFIERS:1]; char *op[MAX_OPERANDS]; int ext_len[MAX_QUALIFIERS?MAX_QUALIFIERS:1]; int op_len[MAX_OPERANDS]; int ext_cnt,op_cnt,inst_len; instruction *ip; while (line = read_next_line()) { if (!cond_state()) { /* skip source until ELSE or ENDIF */ int idx = -1; s = skip(line); if (labname = parse_labeldef(&s,1)) { if (*s == ':') s++; /* skip double-colon */ myfree(labname); s = skip(s); } else { if (inst = skip_identifier(s)) { inst = skip(inst); idx = check_directive(&inst); } } if (idx < 0) idx = check_directive(&s); if (idx >= 0) { if (directives[idx].func == handle_if) cond_skipif(); else if (directives[idx].func == handle_else) cond_else(); else if (directives[idx].func == handle_endif) cond_endif(); } continue; } s = skip(line); again: if (*s=='\0' || *line=='*' || *s==commentchar) continue; if (labname = parse_labeldef(&s,1)) { /* we have found a valid global or local label */ symbol *sym = new_labsym(0,labname); if (*s == ':') { /* double colon automatically declares label as exported */ sym->flags |= EXPORT; s++; } add_atom(0,new_label_atom(sym)); myfree(labname); s = skip(s); } else { /* there can still be a sym. in the 1st fld and an assignm. directive */ inst = s; labname = parse_symbol(&s); if (labname == NULL) { syntax_error(10); /* identifier expected */ continue; } s = skip(s); /* Now we have labname pointing to the first field in the line and s pointing to the second. Find out where the directive is. */ if (!ISEOL(s)) { #ifdef PARSE_CPU_LABEL if (PARSE_CPU_LABEL(labname,&s)) { myfree(labname); continue; } #endif if (handle_directive(s)) { myfree(labname); continue; } } /* directive or mnemonic must be in the first field */ myfree(labname); s = inst; } if (!strnicmp(s,".iif",4) || !(strnicmp(s,"iif",3))) { /* immediate conditional assembly: parse line after ',' when true */ s = skip(*s=='.'?s+4:s+3); if (do_cond(&s)) { s = skip(s); if (*s == ',') { s = skip(s+1); goto again; } else syntax_error(0); /* malformed immediate-if */ } continue; } /* check for directives */ s = parse_cpu_special(s); if (ISEOL(s)) continue; if (handle_directive(s)) continue; /* read mnemonic name */ inst = s; ext_cnt = 0; if (!ISIDSTART(*s)) { syntax_error(10); /* identifier expected */ continue; } #if MAX_QUALIFIERS==0 while (*s && !isspace((unsigned char)*s)) s++; inst_len = s - inst; #else s = parse_instruction(s,&inst_len,ext,ext_len,&ext_cnt); #endif if (!isspace((unsigned char)*s) && *s!='\0') syntax_error(2); /* no space before operands */ s = skip(s); if (execute_macro(inst,inst_len,ext,ext_len,ext_cnt,s)) continue; /* read operands, terminated by comma or blank (unless in parentheses) */ op_cnt = 0; while (!ISEOL(s) && op_cnt<MAX_OPERANDS) { op[op_cnt] = s; s = skip_operand(s); op_len[op_cnt] = oplen(s,op[op_cnt]); #if !ALLOW_EMPTY_OPS if (op_len[op_cnt] <= 0) syntax_error(5); /* missing operand */ else #endif op_cnt++; s = skip(s); if (*s != ',') break; else s = skip(s+1); } eol(s); ip = new_inst(inst,inst_len,op_cnt,op,op_len); #if MAX_QUALIFIERS>0 if (ip) { int i; for (i=0; i<ext_cnt; i++) ip->qualifiers[i] = cnvstr(ext[i],ext_len[i]); for(; i<MAX_QUALIFIERS; i++) ip->qualifiers[i] = NULL; } #endif if (ip) add_atom(0,new_inst_atom(ip)); } cond_check(); /* check for open conditional blocks */ }
void * proxychild(struct clientparam* param) { int res=0, i=0; unsigned char* buf = NULL, *newbuf; int inbuf; int bufsize; unsigned reqlen = 0; unsigned char *sb=NULL, *sg=NULL, *se=NULL, *sp=NULL, *req=NULL, *su=NULL, *ss = NULL; unsigned char *ftpbase=NULL; unsigned char username[1024]; int keepalive = 0; uint64_t contentlength64 = 0; int hascontent =0; int isconnect = 0; int redirect = 0; int prefix = 0, ckeepalive=0; int ftp = 0; int anonymous; int sleeptime = 0; int reqsize, reqbufsize; int authenticate; struct pollfd fds[2]; SOCKET ftps; char ftpbuf[FTPBUFSIZE]; int inftpbuf = 0; #ifndef WITHMAIN FILTER_ACTION action; #endif if(!(buf = myalloc(BUFSIZE))) {RETURN(21);} bufsize = BUFSIZE; anonymous = param->srv->singlepacket; for(;;){ memset(buf, 0, bufsize); inbuf = 0; if(keepalive && (param->cliinbuf == param->clioffset) && (param->remsock != INVALID_SOCKET)){ memset(fds, 0, sizeof(fds)); fds[0].fd = param->clisock; fds[0].events = POLLIN; fds[1].fd = param->remsock; fds[1].events = POLLIN; res = so._poll(fds, 2, conf.timeouts[STRING_S]*1000); if(res<=0) { RETURN(555); } if((fds[1].revents & (POLLIN|POLLHUP|POLLERR|POLLNVAL))) { if(param->transparent || (!param->redirected && param->redirtype == R_HTTP)) RETURN(555); ckeepalive = 0; so._shutdown(param->remsock, SHUT_RDWR); so._closesocket(param->remsock); param->remsock = INVALID_SOCKET; param->redirected = 0; param->redirtype = 0; } } i = sockgetlinebuf(param, CLIENT, buf, LINESIZE - 1, '\n', conf.timeouts[STRING_L]); if(i<=0) { RETURN((keepalive)?555:(i)?507:508); } if (i==2 && buf[0]=='\r' && buf[1]=='\n') continue; buf[i] = 0; if(req) { if(!param->transparent && !param->srv->transparent && param->redirtype != R_HTTP && (i<=prefix || strncasecmp((char *)buf, (char *)req, prefix))){ ckeepalive = 0; if(param->remsock != INVALID_SOCKET){ so._shutdown(param->remsock, SHUT_RDWR); so._closesocket(param->remsock); } param->remsock = INVALID_SOCKET; param->redirected = 0; param->redirtype = 0; } myfree(req); } req = (unsigned char *)mystrdup((char *)buf); if(!req){RETURN(510);} if(i<10) { RETURN(511); } if(buf[i-3] == '1') keepalive = 2; if((isconnect = !strncasecmp((char *)buf, "CONNECT", 7))) keepalive = 2; if ((sb=(unsigned char *)(unsigned char *)strchr((char *)buf, ' ')) == NULL) {RETURN(512);} ss = ++sb; if(!isconnect) { if (!strncasecmp((char *)sb, "http://", 7)) { sb += 7; } else if (!strncasecmp((char *)sb, "ftp://", 6)) { ftp = 1; sb += 6; } else if(*sb == '/') { param->transparent = 1; } else { RETURN (513); } } else { if ((se=(unsigned char *)(unsigned char *)strchr((char *)sb, ' ')) == NULL || sb==se) {RETURN (514);} *se = 0; } if(!param->transparent || isconnect) { if(!isconnect) { if ((se=(unsigned char *)(unsigned char *)strchr((char *)sb, '/')) == NULL || sb==se || !(sg=(unsigned char *)strchr((char *)sb, ' '))) {RETURN (515);} if(se > sg) se=sg; *se = 0; } prefix = (int)(se - buf); su = (unsigned char*)strrchr((char *)sb, '@'); if(su) { su = mystrdup(sb); decodeurl(su, 0); parseconnusername((char *)su, (struct clientparam *)param, 1, (unsigned short)((ftp)?21:80)); myfree(su); } else parsehostname((char *)sb, (struct clientparam *)param, (unsigned short)((ftp)? 21:80)); if(!isconnect){ if(se==sg)*se-- = ' '; *se = '/'; memmove(ss, se, i - (se - sb) + 1); } } reqlen = i = (int)strlen((char *)buf); if(!strncasecmp((char *)buf, "CONNECT", 7))param->operation = HTTP_CONNECT; else if(!strncasecmp((char *)buf, "GET", 3))param->operation = (ftp)?FTP_GET:HTTP_GET; else if(!strncasecmp((char *)buf, "PUT", 3))param->operation = (ftp)?FTP_PUT:HTTP_PUT; else if(!strncasecmp((char *)buf, "POST", 4)||!strncasecmp((char *)buf, "BITS_POST", 9))param->operation = HTTP_POST; else if(!strncasecmp((char *)buf, "HEAD", 4))param->operation = HTTP_HEAD; else param->operation = HTTP_OTHER; do { buf[inbuf+i]=0; /*printf("Got: %s\n", buf+inbuf);*/ #ifndef WITHMAIN if(i > 25 && !param->srv->transparent && (!strncasecmp((char *)(buf+inbuf), "proxy-authorization", 19))){ sb = (unsigned char *)strchr((char *)(buf+inbuf), ':'); if(!sb)continue; ++sb; while(isspace(*sb))sb++; if(!*sb) continue; if(!strncasecmp((char *)sb, "basic", 5)){ sb+=5; while(isspace(*sb))sb++; i = de64(sb, username, 255); if(i<=0)continue; username[i] = 0; sb = (unsigned char *)strchr((char *)username, ':'); if(sb){ *sb = 0; if(param->password)myfree(param->password); param->password = (unsigned char *)mystrdup((char *)sb+1); param->pwtype = 0; } if(param->username)myfree(param->username); param->username = (unsigned char *)mystrdup((char *)username); continue; } #ifndef NOCRYPT if(param->srv->usentlm && !strncasecmp((char *)sb, "ntlm", 4)){ sb+=4; while(isspace(*sb))sb++; i = de64(sb, username, 1023); if(i<=16)continue; username[i] = 0; if(strncasecmp((char *)username, "NTLMSSP", 8)) continue; if(username[8] == 1) { while( (i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){ if(i> 15 && (!strncasecmp((char *)(buf), "content-length", 14))){ buf[i]=0; sscanf((char *)buf + 15, "%"PRINTF_INT64_MODIFIER"u", &contentlength64); } } while( contentlength64 > 0 && (i = sockgetlinebuf(param, CLIENT, buf, (BUFSIZE < contentlength64)? BUFSIZE - 1:(int)contentlength64, '\n', conf.timeouts[STRING_S])) > 0){ if ((uint64_t)i > contentlength64) break; contentlength64-=i; } contentlength64 = 0; if(param->password)myfree(param->password); param->password = myalloc(32); param->pwtype = 2; i = (int)strlen(proxy_stringtable[13]); memcpy(buf, proxy_stringtable[13], i); genchallenge(param, (char *)param->password, (char *)buf + i); memcpy(buf + strlen((char *)buf), "\r\n\r\n", 5); socksend(param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]); ckeepalive = keepalive = 1; goto REQUESTEND; } if(username[8] == 3 && param->pwtype == 2 && i>=80) { unsigned offset, len; len = username[20] + (((unsigned)username[21]) << 8); offset = username[24] + (((unsigned)username[25]) << 8); if(len != 24 || len + offset > (unsigned)i) continue; memcpy(param->password + 8, username + offset, 24); len = username[36] + (((unsigned)username[37]) << 8); offset = username[40] + (((unsigned)username[41]) << 8); if(len> 255 || len + offset > (unsigned)i) continue; if(param->username) myfree(param->username); unicode2text((char *)username+offset, (char *)username+offset, (len>>1)); param->username = (unsigned char *)mystrdup((char *)username+offset); } continue; } #endif }
int smtp_sasl_passwd_lookup(SMTP_SESSION *session) { const char *myname = "smtp_sasl_passwd_lookup"; SMTP_STATE *state = session->state; SMTP_ITERATOR *iter = session->iterator; const char *value; char *passwd; /* * Sanity check. */ if (smtp_sasl_passwd_map == 0) msg_panic("%s: passwd map not initialized", myname); /* * Look up the per-server password information. Try the hostname first, * then try the destination. * * XXX Instead of using nexthop (the intended destination) we use dest * (either the intended destination, or a fall-back destination). * * XXX SASL authentication currently depends on the host/domain but not on * the TCP port. If the port is not :25, we should append it to the table * lookup key. Code for this was briefly introduced into 2.2 snapshots, * but didn't canonicalize the TCP port, and did not append the port to * the MX hostname. */ smtp_sasl_passwd_map->error = 0; if ((smtp_mode && var_smtp_sender_auth && state->request->sender[0] && (value = mail_addr_find(smtp_sasl_passwd_map, state->request->sender, (char **) 0)) != 0) || (smtp_sasl_passwd_map->error == 0 && (value = maps_find(smtp_sasl_passwd_map, STR(iter->host), 0)) != 0) || (smtp_sasl_passwd_map->error == 0 && (value = maps_find(smtp_sasl_passwd_map, STR(iter->dest), 0)) != 0)) { if (session->sasl_username) myfree(session->sasl_username); session->sasl_username = mystrdup(value); passwd = split_at(session->sasl_username, ':'); if (session->sasl_passwd) myfree(session->sasl_passwd); session->sasl_passwd = mystrdup(passwd ? passwd : ""); if (msg_verbose) msg_info("%s: host `%s' user `%s' pass `%s'", myname, STR(iter->host), session->sasl_username, session->sasl_passwd); return (1); } else if (smtp_sasl_passwd_map->error) { msg_warn("%s: %s lookup error", state->request->queue_id, smtp_sasl_passwd_map->title); vstream_longjmp(session->stream, SMTP_ERR_DATA); } else { if (msg_verbose) msg_info("%s: no auth info found (sender=`%s', host=`%s')", myname, state->request->sender, STR(iter->host)); return (0); } }
void * udppmchild(struct clientparam* param) { unsigned char *buf = NULL; int res, i; #ifdef _WIN32 SASIZETYPE size; unsigned long ul = 1; #endif parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport)); if (!param->req.sin_addr.s_addr) { param->srv->fds.events = POLLIN; RETURN (100); } if(!param->clibuf && (!(param->clibuf=myalloc(UDPBUFSIZE)) || !(param->clibufsize = UDPBUFSIZE))){ param->srv->fds.events = POLLIN; RETURN (21); } param->cliinbuf = param->clioffset = 0; i = sockrecvfrom(param->srv->srvsock, ¶m->sinc, param->clibuf, param->clibufsize, 0); if(i<=0){ param->srv->fds.events = POLLIN; RETURN (214); } param->cliinbuf = i; #ifdef _WIN32 if((param->clisock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } if(setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);}; ioctlsocket(param->clisock, FIONBIO, &ul); size = sizeof(struct sockaddr_in); if(getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sins, &size)) {RETURN(21);}; if(bind(param->clisock,(struct sockaddr *)¶m->sins,sizeof(struct sockaddr_in))) { RETURN(822); } #else param->clisock = param->srv->srvsock; #endif param->sins.sin_family = AF_INET; param->sins.sin_port = htons(0); param->sins.sin_addr.s_addr = param->extip; if ((param->remsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} if(bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins))) {RETURN (12);} #ifdef _WIN32 ioctlsocket(param->remsock, FIONBIO, &ul); #else fcntl(param->remsock,F_SETFL,O_NONBLOCK); #endif param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr; param->sins.sin_port = param->req.sin_port; param->operation = UDPASSOC; if((res = (*param->srv->authfunc)(param))) {RETURN(res);} if(param->srv->singlepacket) { param->srv->fds.events = POLLIN; } param->res = sockmap(param, conf.timeouts[(param->srv->singlepacket)?SINGLEBYTE_L:STRING_L]); if(!param->srv->singlepacket) { param->srv->fds.events = POLLIN; } CLEANRET: if(buf)myfree(buf); (*param->srv->logfunc)(param, NULL); #ifndef _WIN32 param->clisock = INVALID_SOCKET; #endif freeparam(param); return (NULL); }
void parse(void) { char *s,*line,*ext[MAX_QUALIFIERS?MAX_QUALIFIERS:1],*op[MAX_OPERANDS]; char *labname,*start; int inst_len,ext_len[MAX_QUALIFIERS?MAX_QUALIFIERS:1],op_len[MAX_OPERANDS]; int ext_cnt,op_cnt; instruction *ip; while (line=read_next_line()){ if (clev >= MAXCONDLEV) syntax_error(16,clev); /* nesting depth exceeded */ if (!cond[clev]) { /* skip source until ELSE or ENDIF */ int idx; s = line; idx = check_directive(&s); if (idx >= 0) { if (!strncmp(directives[idx].name,"if",2)) { ifnesting++; } else if (ifnesting==0 && !strncmp(directives[idx].name,"else",4)) { cond[clev] = 1; } else if (directives[idx].func == handle_endif) { if (ifnesting == 0) { if (clev > 0) clev--; else syntax_error(14); /* endif without if */ } else ifnesting--; } } continue; } s=skip(line); if(handle_directive(s)) continue; /* skip spaces */ s=skip(s); if(!*s||*s==commentchar) continue; /* check for label */ start=s; if(labname=get_local_label(&s)){ /* local label? */ if(*s!=':'){ s=start; myfree(labname); labname=NULL; } } else if(ISIDSTART(*s)){ /* or global label? */ s++; while(ISIDCHAR(*s)) s++; if(*s!=':') s=start; else labname=cnvstr(start,s-start); } if(labname){ /* we have found a valid global or local label */ add_atom(0,new_label_atom(new_labsym(0,labname))); s=skip(s+1); myfree(labname); } if(!*s||*s==commentchar) continue; s=skip(parse_cpu_special(s)); if(*s==0||*s==commentchar) continue; if(handle_directive(s)) continue; /* read mnemonic name */ start=s; ext_cnt=0; if(!ISIDSTART(*s)){ syntax_error(10); continue; } #if MAX_QUALIFIERS==0 while(*s&&!isspace((unsigned char)*s)) s++; inst_len=s-start; #else s=parse_instruction(s,&inst_len,ext,ext_len,&ext_cnt); #endif s=skip(s); if(execute_macro(start,inst_len,ext,ext_len,ext_cnt,s,clev)) continue; /* read operands, terminated by comma (unless in parentheses) */ op_cnt=0; while(*s&&*s!=commentchar&&op_cnt<MAX_OPERANDS){ op[op_cnt]=s; s=skip_operand(s); op_len[op_cnt]=oplen(s,op[op_cnt]); #if !ALLOW_EMPTY_OPS if(op_len[op_cnt]<=0) syntax_error(5); else #endif op_cnt++; s=skip(s); if(*s!=','){ break; }else{ s=skip(s+1); } } s=skip(s); if(*s!=0&&*s!=commentchar) syntax_error(6); ip=new_inst(start,inst_len,op_cnt,op,op_len); #if MAX_QUALIFIERS>0 if(ip){ int i; for(i=0;i<ext_cnt;i++) ip->qualifiers[i]=cnvstr(ext[i],ext_len[i]); for(;i<MAX_QUALIFIERS;i++) ip->qualifiers[i]=0; } #endif if(ip){ add_atom(0,new_inst_atom(ip)); }else ; } if (clev > 0) syntax_error(15); /* if without endif */ }
static int postalias_queries(VSTREAM *in, char **maps, const int map_count, const int dict_flags) { int found = 0; VSTRING *keybuf = vstring_alloc(100); DICT **dicts; const char *map_name; const char *value; int n; /* * Sanity check. */ if (map_count <= 0) msg_panic("postalias_queries: bad map count"); /* * Prepare to open maps lazily. */ dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count); for (n = 0; n < map_count; n++) dicts[n] = 0; /* * Perform all queries. Open maps on the fly, to avoid opening unecessary * maps. */ while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) { for (n = 0; n < map_count; n++) { if (dicts[n] == 0) dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ? dict_open3(maps[n], map_name, O_RDONLY, dict_flags) : dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags)); if ((value = dict_get(dicts[n], STR(keybuf))) != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", dicts[n]->type, dicts[n]->name, STR(keybuf)); msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND", dicts[n]->type, dicts[n]->name); } vstream_printf("%s: %s\n", STR(keybuf), value); found = 1; break; } if (dicts[n]->error) msg_fatal("table %s:%s: query error: %m", dicts[n]->type, dicts[n]->name); } } if (found) vstream_fflush(VSTREAM_OUT); /* * Cleanup. */ for (n = 0; n < map_count; n++) if (dicts[n]) dict_close(dicts[n]); myfree((void *) dicts); vstring_free(keybuf); return (found); }
void pcf_edit_main(int mode, int argc, char **argv) { char *path; EDIT_FILE *ep; VSTREAM *src; VSTREAM *dst; VSTRING *buf = vstring_alloc(100); VSTRING *key = vstring_alloc(10); char *cp; char *pattern; char *edit_value; HTABLE *table; struct cvalue { char *value; int found; }; struct cvalue *cvalue; HTABLE_INFO **ht_info; HTABLE_INFO **ht; int interesting; const char *err; /* * Store command-line parameters for quick lookup. */ table = htable_create(argc); while ((cp = *argv++) != 0) { if (strchr(cp, '\n') != 0) msg_fatal("-e, -X, or -# accepts no multi-line input"); while (ISSPACE(*cp)) cp++; if (*cp == '#') msg_fatal("-e, -X, or -# accepts no comment input"); if (mode & PCF_EDIT_CONF) { if ((err = split_nameval(cp, &pattern, &edit_value)) != 0) msg_fatal("%s: \"%s\"", err, cp); } else if (mode & (PCF_COMMENT_OUT | PCF_EDIT_EXCL)) { if (*cp == 0) msg_fatal("-X or -# requires non-blank parameter names"); if (strchr(cp, '=') != 0) msg_fatal("-X or -# requires parameter names without value"); pattern = cp; trimblanks(pattern, 0); edit_value = 0; } else { msg_panic("pcf_edit_main: unknown mode %d", mode); } cvalue = (struct cvalue *) mymalloc(sizeof(*cvalue)); cvalue->value = edit_value; cvalue->found = 0; htable_enter(table, pattern, (char *) cvalue); } /* * Open a temp file for the result. This uses a deterministic name so we * don't leave behind thrash with random names. */ pcf_set_config_dir(); path = concatenate(var_config_dir, "/", MAIN_CONF_FILE, (char *) 0); if ((ep = edit_file_open(path, O_CREAT | O_WRONLY, 0644)) == 0) msg_fatal("open %s%s: %m", path, EDIT_FILE_SUFFIX); dst = ep->tmp_fp; /* * Open the original file for input. */ if ((src = vstream_fopen(path, O_RDONLY, 0)) == 0) { /* OK to delete, since we control the temp file name exclusively. */ (void) unlink(ep->tmp_path); msg_fatal("open %s for reading: %m", path); } /* * Copy original file to temp file, while replacing parameters on the * fly. Issue warnings for names found multiple times. */ #define STR(x) vstring_str(x) interesting = 0; while ((cp = pcf_next_cf_line(buf, src, dst, (int *) 0)) != 0) { /* Copy, skip or replace continued text. */ if (cp > STR(buf)) { if (interesting == 0) vstream_fputs(STR(buf), dst); else if (mode & PCF_COMMENT_OUT) vstream_fprintf(dst, "#%s", STR(buf)); } /* Copy or replace start of logical line. */ else { vstring_strncpy(key, cp, strcspn(cp, " \t\r\n=")); cvalue = (struct cvalue *) htable_find(table, STR(key)); if ((interesting = !!cvalue) != 0) { if (cvalue->found++ == 1) msg_warn("%s: multiple entries for \"%s\"", path, STR(key)); if (mode & PCF_EDIT_CONF) vstream_fprintf(dst, "%s = %s\n", STR(key), cvalue->value); else if (mode & PCF_COMMENT_OUT) vstream_fprintf(dst, "#%s", cp); } else { vstream_fputs(STR(buf), dst); } } } /* * Generate new entries for parameters that were not found. */ if (mode & PCF_EDIT_CONF) { for (ht_info = ht = htable_list(table); *ht; ht++) { cvalue = (struct cvalue *) ht[0]->value; if (cvalue->found == 0) vstream_fprintf(dst, "%s = %s\n", ht[0]->key, cvalue->value); } myfree((char *) ht_info); } /* * When all is well, rename the temp file to the original one. */ if (vstream_fclose(src)) msg_fatal("read %s: %m", path); if (edit_file_close(ep) != 0) msg_fatal("close %s%s: %m", path, EDIT_FILE_SUFFIX); /* * Cleanup. */ myfree(path); vstring_free(buf); vstring_free(key); htable_free(table, myfree); }
static void output_header(void *context, int header_class, const HEADER_OPTS *header_info, VSTRING *buf, off_t offset) { SM_STATE *state = (SM_STATE *) context; TOK822 *tree; TOK822 **addr_list; TOK822 **tpp; ARGV *rcpt; char *start; char *line; char *next_line; ssize_t len; /* * Parse the header line, and save copies of recipient addresses in the * appropriate place. */ if (header_class == MIME_HDR_PRIMARY && header_info && (header_info->flags & HDR_OPT_RECIP) && (header_info->flags & HDR_OPT_EXTRACT) && (state->resent == 0 || (header_info->flags & HDR_OPT_RR))) { if (header_info->flags & HDR_OPT_RR) { rcpt = state->resent_recip; if (state->resent == 0) state->resent = 1; } else rcpt = state->recipients; tree = tok822_parse(STR(buf) + strlen(header_info->name) + 1); addr_list = tok822_grep(tree, TOK822_ADDR); for (tpp = addr_list; *tpp; tpp++) { tok822_internalize(state->temp, tpp[0]->head, TOK822_STR_DEFL); argv_add(rcpt, STR(state->temp), (char *) 0); } myfree((char *) addr_list); tok822_free_tree(tree); } /* * Pipe the unmodified message header through the header line folding * routine, and ensure that long lines are chopped appropriately. */ for (line = start = STR(buf); line; line = next_line) { next_line = split_at(line, '\n'); len = next_line ? next_line - line - 1 : strlen(line); do { if (len > var_line_limit) { output_text(context, REC_TYPE_CONT, line, var_line_limit, offset); line += var_line_limit; len -= var_line_limit; offset += var_line_limit; } else { output_text(context, REC_TYPE_NORM, line, len, offset); offset += len; break; } } while (len > 0); offset += 1; } }
/* this function computes the vector b(out) given the vector x(in) such as Ax = b, where A is a matrix */ void radtransfer_matrix_multiply(double *in, double *out, double *sum) { int i, j, k, ngrp, dummy, ndone, ndone_flag; int sendTask, recvTask, nexport, nimport, place; double a; /* allocate buffers to arrange communication */ Ngblist = (int *) mymalloc(NumPart * sizeof(int)); All.BunchSize = (int) ((All.BufferSize * 1024 * 1024) / (sizeof(struct data_index) + sizeof(struct data_nodelist) + sizeof(struct radtransferdata_in) + sizeof(struct radtransferdata_out) + sizemax(sizeof(struct radtransferdata_in), sizeof(struct radtransferdata_out)))); DataIndexTable = (struct data_index *) mymalloc(All.BunchSize * sizeof(struct data_index)); DataNodeList = (struct data_nodelist *) mymalloc(All.BunchSize * sizeof(struct data_nodelist)); if(All.ComovingIntegrationOn) a = All.Time; else a = 1.0; i = 0; do /* communication loop */ { for(j = 0; j < NTask; j++) { Send_count[j] = 0; Exportflag[j] = -1; } /* do local particles and prepare export list */ for(nexport = 0; i < N_gas; i++) { if(P[i].Type == 0) #ifdef RT_VAR_DT if(SphP[i].rt_flag == 1) #endif if(radtransfer_evaluate(i, 0, in, out, sum, &nexport, Send_count) < 0) break; } #ifdef MYSORT mysort_dataindex(DataIndexTable, nexport, sizeof(struct data_index), data_index_compare); #else qsort(DataIndexTable, nexport, sizeof(struct data_index), data_index_compare); #endif MPI_Allgather(Send_count, NTask, MPI_INT, Sendcount_matrix, NTask, MPI_INT, MPI_COMM_WORLD); for(j = 0, nimport = 0, Recv_offset[0] = 0, Send_offset[0] = 0; j < NTask; j++) { Recv_count[j] = Sendcount_matrix[j * NTask + ThisTask]; nimport += Recv_count[j]; if(j > 0) { Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1]; Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1]; } } RadTransferDataGet = (struct radtransferdata_in *) mymalloc(nimport * sizeof(struct radtransferdata_in)); RadTransferDataIn = (struct radtransferdata_in *) mymalloc(nexport * sizeof(struct radtransferdata_in)); /* prepare particle data for export */ for(j = 0; j < nexport; j++) { place = DataIndexTable[j].Index; for(k = 0; k < 3; k++) { RadTransferDataIn[j].Pos[k] = P[place].Pos[k]; RadTransferDataIn[j].ET[k] = SphP[place].ET[k]; RadTransferDataIn[j].ET[k + 3] = SphP[place].ET[k + 3]; } RadTransferDataIn[j].Hsml = PPP[place].Hsml; RadTransferDataIn[j].Kappa = Kappa[place]; RadTransferDataIn[j].Lambda = Lambda[place]; RadTransferDataIn[j].Mass = P[place].Mass; RadTransferDataIn[j].Density = SphP[place].d.Density; memcpy(RadTransferDataIn[j].NodeList, DataNodeList[DataIndexTable[j].IndexGet].NodeList, NODELISTLENGTH * sizeof(int)); } /* exchange particle data */ for(ngrp = 1; ngrp < (1 << PTask); ngrp++) { sendTask = ThisTask; recvTask = ThisTask ^ ngrp; if(recvTask < NTask) { if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0) { /* get the particles */ MPI_Sendrecv(&RadTransferDataIn[Send_offset[recvTask]], Send_count[recvTask] * sizeof(struct radtransferdata_in), MPI_BYTE, recvTask, TAG_RT_A, &RadTransferDataGet[Recv_offset[recvTask]], Recv_count[recvTask] * sizeof(struct radtransferdata_in), MPI_BYTE, recvTask, TAG_RT_A, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } } } myfree(RadTransferDataIn); RadTransferDataResult = (struct radtransferdata_out *) mymalloc(nimport * sizeof(struct radtransferdata_out)); RadTransferDataOut = (struct radtransferdata_out *) mymalloc(nexport * sizeof(struct radtransferdata_out)); /* now do the particles that were sent to us */ for(j = 0; j < nimport; j++) radtransfer_evaluate(j, 1, in, out, sum, &dummy, &dummy); if(i < N_gas) ndone_flag = 0; else ndone_flag = 1; MPI_Allreduce(&ndone_flag, &ndone, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); /* get the result */ for(ngrp = 1; ngrp < (1 << PTask); ngrp++) { sendTask = ThisTask; recvTask = ThisTask ^ ngrp; if(recvTask < NTask) { if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0) { /* send the results */ MPI_Sendrecv(&RadTransferDataResult[Recv_offset[recvTask]], Recv_count[recvTask] * sizeof(struct radtransferdata_out), MPI_BYTE, recvTask, TAG_RT_B, &RadTransferDataOut[Send_offset[recvTask]], Send_count[recvTask] * sizeof(struct radtransferdata_out), MPI_BYTE, recvTask, TAG_RT_B, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } } } /* add the result to the local particles */ for(j = 0; j < nexport; j++) { place = DataIndexTable[j].Index; out[place] += RadTransferDataOut[j].Out; sum[place] += RadTransferDataOut[j].Sum; } myfree(RadTransferDataOut); myfree(RadTransferDataResult); myfree(RadTransferDataGet); } while(ndone < NTask); /* do final operations on results */ for(i = 0; i < N_gas; i++) if(P[i].Type == 0) { #ifdef RT_VAR_DT if(SphP[i].rt_flag == 0) { sum[i] = 0.0; out[i] = 0.0; } else #endif { /* divide c_light by a to get comoving speed of light (because kappa is comoving) */ if((1 + dt * (c_light / a) * Kappa[i] + sum[i]) < 0) { printf("1 + sum + rate= %g sum=%g rate=%g i =%d\n", 1 + dt * (c_light / a) * Kappa[i] + sum[i], sum[i], dt * (c_light / a) * Kappa[i], i); endrun(123); } sum[i] += 1.0 + dt * (c_light / a) * Kappa[i]; out[i] += in[i] * sum[i]; } } myfree(DataNodeList); myfree(DataIndexTable); myfree(Ngblist); }
static void dict_mysql_close(DICT *dict) { DICT_MYSQL *dict_mysql = (DICT_MYSQL *) dict; plmysql_dealloc(dict_mysql->pldb); cfg_parser_free(dict_mysql->parser); myfree(dict_mysql->username); myfree(dict_mysql->password); myfree(dict_mysql->dbname); myfree(dict_mysql->query); myfree(dict_mysql->result_format); if (dict_mysql->option_file) myfree(dict_mysql->option_file); if (dict_mysql->option_group) myfree(dict_mysql->option_group); #if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 if (dict_mysql->tls_key_file) myfree(dict_mysql->tls_key_file); if (dict_mysql->tls_cert_file) myfree(dict_mysql->tls_cert_file); if (dict_mysql->tls_CAfile) myfree(dict_mysql->tls_CAfile); if (dict_mysql->tls_CApath) myfree(dict_mysql->tls_CApath); if (dict_mysql->tls_ciphers) myfree(dict_mysql->tls_ciphers); #endif if (dict_mysql->hosts) argv_free(dict_mysql->hosts); if (dict_mysql->ctx) db_common_free_ctx(dict_mysql->ctx); if (dict->fold_buf) vstring_free(dict->fold_buf); dict_free(dict); }