/* * Copyright (c) 2002-2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: qmgr_stop.c,v 1.62 2006/04/02 06:34:19 ca Exp $") #include "sm/error.h" #include "sm/assert.h" #include "sm/qmgr.h" #include "sm/qmgr-int.h" #include "qmgr.h" /* ** QMGR_STOP -- stop QMGR ** ** Parameters: ** qmgr_ctx -- QMGR context ** ** Returns: ** usual sm_error code */ /* should we pass type of shutdown? immediate, normal, ...? */ sm_ret_T qmgr_stop(qmgr_ctx_P qmgr_ctx) { int i; sm_ret_T ret; bool resource_problem; SM_REQUIRE(qmgr_ctx != NULL); QM_LEV_DPRINTFC(QDC_STOP, 4, (QM_DEBFP, "qmgr_stop\n")); if (qmgr_ctx->qmgr_status < QMGR_ST_INIT1) return SM_SUCCESS; resource_problem = (qmgr_ctx->qmgr_status == QMGR_ST_RSR); qmgr_ctx->qmgr_status = QMGR_ST_SH_DOWN; /* ** How to properly shut down the system? ** In which order? Which tasks need to be called for termination? ** For example: ibdb task to commit data and tell servers about it? */ CLOSE_FD(qmgr_ctx->qmgr_ss_li.qm_gli_lfd); CLOSE_FD(qmgr_ctx->qmgr_sc_li.qm_gli_lfd); /* CLOSE_FD(qmgr_ctx->qmgr_ar_fd); */ CLOSE_FD(qmgr_ctx->qmgr_ctllfd); (void) sm_rcbcom_close(&qmgr_ctx->qmgr_ctl_com); if (qmgr_ctx->qmgr_ev_ctx != NULL) ret = evthr_stop(qmgr_ctx->qmgr_ev_ctx); /* complain on error? */ if (qmgr_ctx->qmgr_ibdb != NULL) { /* check status, shutdown other connections etc */ ret = ibdb_commit(qmgr_ctx->qmgr_ibdb); ret = ibdb_close(qmgr_ctx->qmgr_ibdb); /* complain on error? */ } if (qmgr_ctx->qmgr_iqdb != NULL) iqdb_close(qmgr_ctx->qmgr_iqdb); /* lock qmgr_ctx? */ /* XXX free the data in qmgr_ctx? */ for (i = 0; i < QM_N_SS_GLI(qmgr_ctx); i++) { (void) qss_ctx_free(qmgr_li_ss(qmgr_ctx, i)); qmgr_li_ss_lv(qmgr_ctx, i) = NULL; } if (qmgr_ctx->qmgr_optas != NULL) { SM_FREE(qmgr_ctx->qmgr_optas->qot_tas); (void) pthread_mutex_destroy(&qmgr_ctx->qmgr_optas->qot_mutex); sm_free_size(qmgr_ctx->qmgr_optas, sizeof(*qmgr_ctx->qmgr_optas)); } for (i = 0; i < QM_N_SC_GLI(qmgr_ctx); i++) { (void) qsc_ctx_free(qmgr_li_sc(qmgr_ctx, i)); qmgr_li_sc_lv(qmgr_ctx, i) = NULL; } ret = qcleanup_ctx_free(qmgr_ctx->qmgr_cleanup_ctx); /* close active envelope db */ QM_LEV_DPRINTFC(QDC_STOP, 3, (QM_DEBFP, "func=qmgr_stop, aq_usage=%d\n", aq_usage(qmgr_ctx->qmgr_aq, AQ_USAGE_ALL))); ret = aq_close(qmgr_ctx->qmgr_aq); /* complain on error? */ ret = qar_ctx_free(qmgr_ctx->qmgr_ar_ctx); /* complain on error? */ if (qmgr_ctx->qmgr_edb != NULL) ret = edb_close(qmgr_ctx->qmgr_edb); /* complain on error? */ if (qmgr_ctx->qmgr_edbc != NULL) ret = edbc_close(qmgr_ctx->qmgr_edbc); /* complain on error? */ ret = edb_fsctx_close(qmgr_ctx->qmgr_edb_fsctx); ret = cdb_fsctx_close(qmgr_ctx->qmgr_cdb_fsctx); ret = fs_ctx_close(qmgr_ctx->qmgr_fs_ctx); if (qmgr_ctx->qmgr_conf_map != NULL) { (void) sm_map_close(qmgr_ctx->qmgr_conf_map, 0); qmgr_ctx->qmgr_conf_map = NULL; } if (qmgr_ctx->qmgr_maps != NULL) { (void) sm_maps_term(qmgr_ctx->qmgr_maps); qmgr_ctx->qmgr_maps = NULL; } ret = occ_close(qmgr_ctx->qmgr_occ_ctx); ret = ssocc_close(qmgr_ctx->qmgr_ssocc_ctx); sm_log_destroy(qmgr_ctx->qmgr_lctx); /* destroy mutex first? */ ret = thr_stop(); if (sm_is_err(ret)) goto error; SM_STR_FREE(qmgr_ctx->qmgr_hostname); SM_STR_FREE(qmgr_ctx->qmgr_pm_addr); qmgr_ctx->qmgr_status = QMGR_ST_STOPPED; (void) pthread_mutex_destroy(&qmgr_ctx->qmgr_mutex); QM_LEV_DPRINTFC(QDC_STOP, 4, (QM_DEBFP, "func=qmgr_stop, status=done\n")); return resource_problem ? sm_err_temp(SM_E_RSR_PRB) : SM_SUCCESS; error: return resource_problem ? sm_err_temp(SM_E_RSR_PRB) : ret; }