/* * v_dtoh -- * Move all but the current screen to the hidden queue. */ static void v_dtoh(SCR *sp) { GS *gp; SCR *tsp; WIN *wp; int hidden; /* Move all screens to the hidden queue, tossing screen maps. */ for (hidden = 0, gp = sp->gp, wp = sp->wp; (tsp = wp->scrq.cqh_first) != (void *)&wp->scrq; ++hidden) { if (_HMAP(tsp) != NULL) { free(_HMAP(tsp)); _HMAP(tsp) = NULL; } CIRCLEQ_REMOVE(&wp->scrq, tsp, q); CIRCLEQ_INSERT_TAIL(&gp->hq, tsp, q); /* XXXX Change if hidden screens per window */ tsp->wp = 0; gp->scr_discard(tsp, NULL); } /* Move current screen back to the display queue. */ CIRCLEQ_REMOVE(&gp->hq, sp, q); CIRCLEQ_INSERT_TAIL(&wp->scrq, sp, q); sp->wp = wp; if (hidden > 1) msgq(sp, M_INFO, "319|%d screens backgrounded; use :display to list them", hidden - 1); }
int rem_client(int pos, struct chain_socket *cs) { int active = cs == client_list.cqh_first; DEBUG(int fd = cs->sock); DEBUG(pid_t pid = cs->pid); memmove(pfds+pos, pfds+pos+1, (client_count-1)*sizeof(struct pollfd)); CIRCLEQ_REMOVE(&client_list, cs, chain); free(cs); client_count--; if(client_list.cqh_first != (void*)&client_list) { if(active) { if((cs = client_list_rotate_next(0))->hide) DEBUG(printf("Active client removed [%i] %i, switch invisible [%i] %i\n", fd, pid, cs->sock, cs->pid)); else DEBUG(printf("Active client removed [%i] %i, switch [%i] %i\n", fd, pid, cs->sock, cs->pid)); return 1; } else { DEBUG(printf("Client removed [%i] %i\n", fd, pid)); return 0; } } else { DEBUG(printf("Active client removed [%i] %i, last\n", fd, pid)); return 0; } }
/* log a line to cur_connection's log */ static void peerlog(const char *prefix, const char *m) { if (cur_connection == NULL) { /* we can not log it in this case. Oh well. */ return; } if (cur_connection->log_file == NULL) { open_peerlog(cur_connection); } /* despite our attempts above, we may not be able to open the file. */ if (cur_connection->log_file != NULL) { char datebuf[32]; time_t n; struct tm *t; time(&n); t = localtime(&n); strftime(datebuf, sizeof(datebuf), "%Y-%m-%d %T", t); fprintf(cur_connection->log_file, "%s %s%s\n", datebuf, prefix, m); /* now move it to the front of the list */ CIRCLEQ_REMOVE(&perpeer_list, cur_connection, log_link); CIRCLEQ_INSERT_HEAD(&perpeer_list, cur_connection, log_link); } }
void in6_pcbdetach(struct in6pcb *in6p) { struct socket *so = in6p->in6p_socket; int s; if (in6p->in6p_af != AF_INET6) return; #if defined(IPSEC) || defined(FAST_IPSEC) ipsec6_delete_pcbpolicy(in6p); #endif /* IPSEC */ so->so_pcb = 0; if (in6p->in6p_options) m_freem(in6p->in6p_options); if (in6p->in6p_outputopts != NULL) { ip6_clearpktopts(in6p->in6p_outputopts, -1); free(in6p->in6p_outputopts, M_IP6OPT); } rtcache_free(&in6p->in6p_route); ip6_freemoptions(in6p->in6p_moptions); s = splnet(); in6_pcbstate(in6p, IN6P_ATTACHED); LIST_REMOVE(&in6p->in6p_head, inph_lhash); CIRCLEQ_REMOVE(&in6p->in6p_table->inpt_queue, &in6p->in6p_head, inph_queue); pool_put(&in6pcb_pool, in6p); splx(s); sofree(so); /* drops the socket's lock */ mutex_enter(softnet_lock); /* reacquire it */ }
void free_clients() { struct chain_socket *cs; while((cs = client_list.cqh_first) != (void*)&client_list) { CIRCLEQ_REMOVE(&client_list, cs, chain); free(cs); } }
/* * file_add -- * Insert a file name into the FREF list, if it doesn't already * appear in it. * * !!! * The "if it doesn't already appear" changes vi's semantics slightly. If * you do a "vi foo bar", and then execute "next bar baz", the edit of bar * will reflect the line/column of the previous edit session. Historic nvi * did not do this. The change is a logical extension of the change where * vi now remembers the last location in any file that it has ever edited, * not just the previously edited file. * * PUBLIC: FREF *file_add __P((SCR *, char *)); */ FREF * file_add(SCR *sp, char *name) { GS *gp; FREF *frp, *tfrp; /* * Return it if it already exists. Note that we test against the * user's name, whatever that happens to be, including if it's a * temporary file. * * If the user added a file but was unable to initialize it, there * can be file list entries where the name field is NULL. Discard * them the next time we see them. */ gp = sp->gp; if (name != NULL) for (frp = gp->frefq.cqh_first; frp != (FREF *)&gp->frefq; frp = frp->q.cqe_next) { if (frp->name == NULL) { tfrp = frp->q.cqe_next; CIRCLEQ_REMOVE(&gp->frefq, frp, q); if (frp->name != NULL) free(frp->name); free(frp); frp = tfrp; continue; } if (!strcmp(frp->name, name)) return (frp); } /* Allocate and initialize the FREF structure. */ CALLOC(sp, frp, FREF *, 1, sizeof(FREF)); if (frp == NULL) return (NULL); /* * If no file name specified, or if the file name is a request * for something temporary, file_init() will allocate the file * name. Temporary files are always ignored. */ if (name != NULL && strcmp(name, TEMPORARY_FILE_STRING) && (frp->name = strdup(name)) == NULL) { free(frp); msgq(sp, M_SYSERR, NULL); return (NULL); } /* Append into the chain of file names. */ CIRCLEQ_INSERT_TAIL(&gp->frefq, frp, q); return (frp); }
static void perpeer_logclose(struct connection *c) { /* only free/close things if we had used them! */ if (c->log_file != NULL) { passert(perpeer_count > 0); CIRCLEQ_REMOVE(&perpeer_list, c, log_link); perpeer_count--; fclose(c->log_file); c->log_file = NULL; } }
/* * Close specified map. */ void ypdb_close_map(struct opt_map *map) { CIRCLEQ_REMOVE(&maps, map, mapsq); /* remove from LRU circleq */ LIST_REMOVE(map, mapsl); /* remove from domain list */ #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_close_map: closing map %s in domain %s [db=%p]", map->map, map->dom->domain, map->db); #endif ypdb_close(map->db); /* close DB */ free(map->map); /* free map name */ free(map); /* free map */ }
/** * De-regsiter a thread and de-allocate all resources. This function * should be called when a thread exits. */ void rec_sched_deregister_thread(struct task** t_ptr) { struct task* t = *t_ptr; pid_t tid = t->tid; struct tasklist_entry* entry = get_entry(tid); if (entry == current_entry) { current_entry = next_entry(entry); if (entry == current_entry) { assert(num_active_threads == 1); current_entry = NULL; } } /* We expect tasks to usually exit by a call to exit() or * exit_group(), so it's not helpful to warn about that. */ if (FIXEDSTACK_DEPTH(&t->pending_events) > 2 || !(t->ev->type == EV_SYSCALL && (SYS_exit == t->ev->syscall.no || SYS_exit_group == t->ev->syscall.no))) { log_warn("%d still has pending events. From top down:", t->tid); log_pending_events(t); } task_group_remove_and_unref(t); CIRCLEQ_REMOVE(&head, entry, entries); tid_to_entry[tid] = NULL; num_active_threads--; assert(num_active_threads >= 0); /* delete all counter data */ cleanup_hpc(t); sys_close(t->child_mem_fd); close(t->desched_fd); detach_and_reap(t); /* finally, free the memory */ sighandlers_unref(&t->sighandlers); sys_free((void**)entry); *t_ptr = NULL; }
/* log a line to cur_connection's log */ static void peerlog(const char *prefix, const char *m) { if (cur_connection == NULL) { /* we can not log it in this case. Oh well. */ return; } if (cur_connection->log_file == NULL) { open_peerlog(cur_connection); } /* despite our attempts above, we may not be able to open the file. */ if (cur_connection->log_file != NULL) { fprintf(cur_connection->log_file, "%s %s%s\n", oswtimestr(), prefix, m); /* now move it to the front of the list */ CIRCLEQ_REMOVE(&perpeer_list, cur_connection, log_link); CIRCLEQ_INSERT_HEAD(&perpeer_list, cur_connection, log_link); } }
/* * ex_txt -- * Get lines from the terminal for ex. * * PUBLIC: int ex_txt __P((SCR *, TEXTH *, ARG_CHAR_T, u_int32_t)); */ int ex_txt(SCR *sp, TEXTH *tiqh, ARG_CHAR_T prompt, u_int32_t flags) { EVENT ev; GS *gp; TEXT ait, *ntp, *tp; carat_t carat_st; size_t cnt; int rval; rval = 0; /* * Get a TEXT structure with some initial buffer space, reusing the * last one if it's big enough. (All TEXT bookkeeping fields default * to 0 -- text_init() handles this.) */ if (tiqh->cqh_first != (void *)tiqh) { tp = tiqh->cqh_first; if (tp->q.cqe_next != (void *)tiqh || tp->lb_len < 32) { text_lfree(tiqh); goto newtp; } tp->len = 0; } else { newtp: if ((tp = text_init(sp, NULL, 0, 32)) == NULL) goto err; CIRCLEQ_INSERT_HEAD(tiqh, tp, q); } /* Set the starting line number. */ tp->lno = sp->lno + 1; /* * If it's a terminal, set up autoindent, put out the prompt, and * set it up so we know we were suspended. Otherwise, turn off * the autoindent flag, as that requires less special casing below. * * XXX * Historic practice is that ^Z suspended command mode (but, because * it ran in cooked mode, it was unaffected by the autowrite option.) * On restart, any "current" input was discarded, whether in insert * mode or not, and ex was in command mode. This code matches historic * practice, but not 'cause it's easier. */ gp = sp->gp; if (F_ISSET(gp, G_SCRIPTED)) LF_CLR(TXT_AUTOINDENT); else { if (LF_ISSET(TXT_AUTOINDENT)) { LF_SET(TXT_EOFCHAR); if (v_txt_auto(sp, sp->lno, NULL, 0, tp)) goto err; } txt_prompt(sp, tp, prompt, flags); } for (carat_st = C_NOTSET;;) { if (v_event_get(sp, &ev, 0, 0)) goto err; /* Deal with all non-character events. */ switch (ev.e_event) { case E_CHARACTER: break; case E_ERR: goto err; case E_REPAINT: case E_WRESIZE: continue; case E_EOF: rval = 1; /* FALLTHROUGH */ case E_INTERRUPT: /* * Handle EOF/SIGINT events by discarding partially * entered text and returning. EOF returns failure, * E_INTERRUPT returns success. */ goto notlast; default: v_event_err(sp, &ev); goto notlast; } /* * Deal with character events. * * Check to see if the character fits into the input buffer. * (Use tp->len, ignore overwrite and non-printable chars.) */ BINC_GOTOW(sp, tp->lb, tp->lb_len, tp->len + 1); switch (ev.e_value) { case K_CR: /* * !!! * Historically, <carriage-return>'s in the command * weren't special, so the ex parser would return an * unknown command error message. However, if they * terminated the command if they were in a map. I'm * pretty sure this still isn't right, but it handles * what I've seen so far. */ if (!FL_ISSET(ev.e_flags, CH_MAPPED)) goto ins_ch; /* FALLTHROUGH */ case K_NL: /* * '\' can escape <carriage-return>/<newline>. We * don't discard the backslash because we need it * to get the <newline> through the ex parser. */ if (LF_ISSET(TXT_BACKSLASH) && tp->len != 0 && tp->lb[tp->len - 1] == '\\') goto ins_ch; /* * CR returns from the ex command line. * * XXX * Terminate with a nul, needed by filter. */ if (LF_ISSET(TXT_CR)) { tp->lb[tp->len] = '\0'; goto done; } /* * '.' may terminate text input mode; free the current * TEXT. */ if (LF_ISSET(TXT_DOTTERM) && tp->len == tp->ai + 1 && tp->lb[tp->len - 1] == '.') { notlast: CIRCLEQ_REMOVE(tiqh, tp, q); text_free(tp); goto done; } /* Set up bookkeeping for the new line. */ if ((ntp = text_init(sp, NULL, 0, 32)) == NULL) goto err; ntp->lno = tp->lno + 1; /* * Reset the autoindent line value. 0^D keeps the ai * line from changing, ^D changes the level, even if * there were no characters in the old line. Note, if * using the current tp structure, use the cursor as * the length, the autoindent characters may have been * erased. */ if (LF_ISSET(TXT_AUTOINDENT)) { if (carat_st == C_NOCHANGE) { if (v_txt_auto(sp, OOBLNO, &ait, ait.ai, ntp)) goto err; free(ait.lb); } else if (v_txt_auto(sp, OOBLNO, tp, tp->len, ntp)) goto err; carat_st = C_NOTSET; } txt_prompt(sp, ntp, prompt, flags); /* * Swap old and new TEXT's, and insert the new TEXT * into the queue. */ tp = ntp; CIRCLEQ_INSERT_TAIL(tiqh, tp, q); break; case K_CARAT: /* Delete autoindent chars. */ if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT)) carat_st = C_CARATSET; goto ins_ch; case K_ZERO: /* Delete autoindent chars. */ if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT)) carat_st = C_ZEROSET; goto ins_ch; case K_CNTRLD: /* Delete autoindent char. */ /* * !!! * Historically, the ^D command took (but then ignored) * a count. For simplicity, we don't return it unless * it's the first character entered. The check for len * equal to 0 is okay, TXT_AUTOINDENT won't be set. */ if (LF_ISSET(TXT_CNTRLD)) { for (cnt = 0; cnt < tp->len; ++cnt) if (!isblank(tp->lb[cnt])) break; if (cnt == tp->len) { tp->len = 1; tp->lb[0] = ev.e_c; tp->lb[1] = '\0'; /* * Put out a line separator, in case * the command fails. */ (void)putchar('\n'); goto done; } } /* * POSIX 1003.1b-1993, paragraph 7.1.1.9, states that * the EOF characters are discarded if there are other * characters to process in the line, i.e. if the EOF * is not the first character in the line. For this * reason, historic ex discarded the EOF characters, * even if occurring in the middle of the input line. * We match that historic practice. * * !!! * The test for discarding in the middle of the line is * done in the switch, because the CARAT forms are N+1, * not N. * * !!! * There's considerable magic to make the terminal code * return the EOF character at all. See that code for * details. */ if (!LF_ISSET(TXT_AUTOINDENT) || tp->len == 0) continue; switch (carat_st) { case C_CARATSET: /* ^^D */ if (tp->len > tp->ai + 1) continue; /* Save the ai string for later. */ ait.lb = NULL; ait.lb_len = 0; BINC_GOTOW(sp, ait.lb, ait.lb_len, tp->ai); MEMCPYW(ait.lb, tp->lb, tp->ai); ait.ai = ait.len = tp->ai; carat_st = C_NOCHANGE; goto leftmargin; case C_ZEROSET: /* 0^D */ if (tp->len > tp->ai + 1) continue; carat_st = C_NOTSET; leftmargin: (void)gp->scr_ex_adjust(sp, EX_TERM_CE); tp->ai = tp->len = 0; break; case C_NOTSET: /* ^D */ if (tp->len > tp->ai) continue; if (txt_dent(sp, tp)) goto err; break; default: abort(); } /* Clear and redisplay the line. */ (void)gp->scr_ex_adjust(sp, EX_TERM_CE); txt_prompt(sp, tp, prompt, flags); break; default: /* * See the TXT_BEAUTIFY comment in vi/v_txt_ev.c. * * Silently eliminate any iscntrl() character that was * not already handled specially, except for <tab> and * <ff>. */ ins_ch: if (LF_ISSET(TXT_BEAUTIFY) && ISCNTRL(ev.e_c) && ev.e_value != K_FORMFEED && ev.e_value != K_TAB) break; tp->lb[tp->len++] = ev.e_c; break; } } /* NOTREACHED */ done: return (rval); err: alloc_err: return (1); }
/* * ypdb_open_db */ DBM * ypdb_open_db(const char *domain, const char *map, u_int *status, struct opt_map **map_info) { static const char *domain_key = YP_INTERDOMAIN_KEY; static const char *secure_key = YP_SECURE_KEY; char map_path[MAXPATHLEN]; struct stat finfo; struct opt_domain *d = NULL; struct opt_map *m = NULL; DBM *db; datum k, v; *status = YP_TRUE; /* defaults to true */ /* * check for illegal domain and map names */ if (_yp_invalid_domain(domain)) { *status = YP_NODOM; return (NULL); } if (_yp_invalid_map(map)) { *status = YP_NOMAP; return (NULL); } /* * check for domain, file. */ (void)snprintf(map_path, sizeof(map_path), "%s/%s", YP_DB_PATH, domain); if (stat(map_path, &finfo) < 0 || !S_ISDIR(finfo.st_mode)) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: no domain %s (map=%s)", domain, map); #endif *status = YP_NODOM; } else { (void)snprintf(map_path, sizeof(map_path), "%s/%s/%s%s", YP_DB_PATH, domain, map, YPDB_SUFFIX); if (stat(map_path, &finfo) < 0) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: no map %s (domain=%s)", map, domain); #endif *status = YP_NOMAP; } } /* * check for preloaded domain, map */ for (d = doms.lh_first; d != NULL; d = d->domsl.le_next) if (strcmp(domain, d->domain) == 0) break; if (d) for (m = d->dmaps.lh_first; m != NULL; m = m->mapsl.le_next) if (strcmp(map, m->map) == 0) break; /* * map found open? */ if (m) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: cached open: domain=%s, map=%s, db=%p,", domain, map, m->db); syslog(LOG_DEBUG, "\tdbdev %d new %d; dbino %d new %d; dbmtime %ld new %ld", m->dbdev, finfo.st_dev, m->dbino, finfo.st_ino, (long) m->dbmtime, (long) finfo.st_mtime); #endif /* * if status != YP_TRUE, then this cached database is now * non-existent */ if (*status != YP_TRUE) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: cached db is now unavailable - " "closing: status %s", yperr_string(ypprot_err(*status))); #endif ypdb_close_map(m); return (NULL); } /* * is this the same db? */ if (finfo.st_dev == m->dbdev && finfo.st_ino == m->dbino && finfo.st_mtime == m->dbmtime) { CIRCLEQ_REMOVE(&maps, m, mapsq); /* adjust LRU queue */ CIRCLEQ_INSERT_HEAD(&maps, m, mapsq); if (map_info) *map_info = m; return (m->db); } else { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: db changed; closing"); #endif ypdb_close_map(m); m = NULL; } } /* * not cached and non-existent, return */ if (*status != YP_TRUE) return (NULL); /* * open map */ (void)snprintf(map_path, sizeof(map_path), "%s/%s/%s", YP_DB_PATH, domain, map); #ifdef OPTIMIZE_DB retryopen: #endif /* OPTIMIZE_DB */ db = ypdb_open(map_path); #ifdef OPTIMIZE_DB if (db == NULL) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: errno %d (%s)", errno, strerror(errno)); #endif /* DEBUG */ if ((errno == ENFILE) || (errno == EMFILE)) { ypdb_close_last(); goto retryopen; } } #endif /* OPTIMIZE_DB */ *status = YP_NOMAP; /* see note below */ if (db == NULL) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: ypdb_open FAILED: map %s (domain=%s)", map, domain); #endif return (NULL); } /* * note: status now YP_NOMAP */ if (d == NULL) { /* allocate new domain? */ d = (struct opt_domain *) malloc(sizeof(*d)); if (d) d->domain = strdup(domain); if (d == NULL || d->domain == NULL) { syslog(LOG_ERR, "ypdb_open_db: MALLOC failed"); ypdb_close(db); if (d) free(d); return (NULL); } LIST_INIT(&d->dmaps); LIST_INSERT_HEAD(&doms, d, domsl); #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: NEW DOMAIN %s", domain); #endif } /* * m must be NULL since we couldn't find a map. allocate new one */ m = (struct opt_map *) malloc(sizeof(*m)); if (m) m->map = strdup(map); if (m == NULL || m->map == NULL) { if (m) free(m); syslog(LOG_ERR, "ypdb_open_db: MALLOC failed"); ypdb_close(db); return (NULL); } m->db = db; m->dom = d; m->host_lookup = FALSE; m->dbdev = finfo.st_dev; m->dbino = finfo.st_ino; m->dbmtime = finfo.st_mtime; CIRCLEQ_INSERT_HEAD(&maps, m, mapsq); LIST_INSERT_HEAD(&d->dmaps, m, mapsl); if (strcmp(map, YP_HOSTNAME) == 0 || strcmp(map, YP_HOSTADDR) == 0) { if (!usedns) { k.dptr = domain_key; k.dsize = YP_INTERDOMAIN_LEN; v = ypdb_fetch(db, k); if (v.dptr) m->host_lookup = TRUE; } else m->host_lookup = TRUE; } m->secure = FALSE; k.dptr = secure_key; k.dsize = YP_SECURE_LEN; v = ypdb_fetch(db, k); if (v.dptr != NULL) m->secure = TRUE; *status = YP_TRUE; if (map_info) *map_info = m; #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: NEW MAP domain=%s, map=%s, hl=%d, s=%d, db=%p", domain, map, m->host_lookup, m->secure, m->db); #endif return (m->db); }
/* * file_end -- * Stop editing a file. * * PUBLIC: int file_end __P((SCR *, EXF *, int)); */ int file_end(SCR *sp, EXF *ep, int force) { FREF *frp; /* * !!! * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER. * (If argument ep is NULL, use sp->ep.) * * If multiply referenced, just decrement the count and return. */ if (ep == NULL) ep = sp->ep; CIRCLEQ_REMOVE(&ep->scrq, sp, eq); if (--ep->refcnt != 0) return (0); /* * * Clean up the FREF structure. * * Save the cursor location. * * XXX * It would be cleaner to do this somewhere else, but by the time * ex or vi knows that we're changing files it's already happened. */ frp = sp->frp; frp->lno = sp->lno; frp->cno = sp->cno; F_SET(frp, FR_CURSORSET); /* * We may no longer need the temporary backing file, so clean it * up. We don't need the FREF structure either, if the file was * never named, so lose it. * * !!! * Re: FR_DONTDELETE, see the comment above in file_init(). */ if (!F_ISSET(frp, FR_DONTDELETE) && frp->tname != NULL) { if (unlink(frp->tname)) msgq_str(sp, M_SYSERR, frp->tname, "240|%s: remove"); free(frp->tname); frp->tname = NULL; if (F_ISSET(frp, FR_TMPFILE)) { CIRCLEQ_REMOVE(&sp->gp->frefq, frp, q); if (frp->name != NULL) free(frp->name); free(frp); } sp->frp = NULL; } /* * Clean up the EXF structure. * * Close the db structure. */ if (ep->db->close != NULL) { if ((sp->db_error = ep->db->close(ep->db, DB_NOSYNC)) != 0 && !force) { msgq_str(sp, M_DBERR, frp->name, "241|%s: close"); CIRCLEQ_INSERT_HEAD(&ep->scrq, sp, eq); ++ep->refcnt; return (1); } ep->db = NULL; } /* COMMITTED TO THE CLOSE. THERE'S NO GOING BACK... */ /* Stop logging. */ (void)log_end(sp, ep); /* Free up any marks. */ (void)mark_end(sp, ep); if (ep->env) { DB_ENV *env; ep->env->close(ep->env, 0); ep->env = 0; if ((sp->db_error = db_env_create(&env, 0))) msgq(sp, M_DBERR, "env_create"); if ((sp->db_error = db_env_remove(env, ep->env_path, 0))) msgq(sp, M_DBERR, "env->remove"); if (ep->env_path != NULL && rmdir(ep->env_path)) msgq_str(sp, M_SYSERR, ep->env_path, "242|%s: remove"); } /* * Delete recovery files, close the open descriptor, free recovery * memory. See recover.c for a description of the protocol. * * XXX * Unlink backup file first, we can detect that the recovery file * doesn't reference anything when the user tries to recover it. * There's a race, here, obviously, but it's fairly small. */ if (!F_ISSET(ep, F_RCV_NORM)) { if (ep->rcv_path != NULL && unlink(ep->rcv_path)) msgq_str(sp, M_SYSERR, ep->rcv_path, "242|%s: remove"); if (ep->rcv_mpath != NULL && unlink(ep->rcv_mpath)) msgq_str(sp, M_SYSERR, ep->rcv_mpath, "243|%s: remove"); } CIRCLEQ_REMOVE(&sp->gp->exfq, ep, q); if (ep->fd != -1) (void)close(ep->fd); if (ep->fcntl_fd != -1) (void)close(ep->fcntl_fd); if (ep->rcv_fd != -1) (void)close(ep->rcv_fd); if (ep->env_path != NULL) free(ep->env_path); if (ep->rcv_path != NULL) free(ep->rcv_path); if (ep->rcv_mpath != NULL) free(ep->rcv_mpath); free(ep); return (0); }