static char rcsid[] = "@(#)$Id: cancel.c,v 1.6 2006/07/24 18:45:00 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.6 $ $State: Exp $ * * Author: Kari Hurtta *****************************************************************************/ #include "headers.h" #include "s_me.h" DEBUG_VAR(Debug,__FILE__,"ui"); static void cancel_set_ttysig_d P_((void)); static void cancel_set_ttysig_d() { /* NULL */ } static cancel_set_ttysig_f * SET_TTYSIG = &cancel_set_ttysig_d; static void cancel_reset_ttysig_d P_((void)); static void cancel_reset_ttysig_d() { /* NULL */ } static cancel_reset_ttysig_f * RESET_TTYSIG = &cancel_reset_ttysig_d; static void cancel_transient_d P_((struct string *x)); static void cancel_transient_d(x) struct string *x; { lib_transient(FRM("%S"),x); } static cancel_transient_f * TRANSIENT = &cancel_transient_d; static void cancel_clear_d P_((void)); static void cancel_clear_d() { lib_transient(FRM("")); } static cancel_clear_f * CLEAR = &cancel_clear_d; extern void setup_cancel_cb(cancel_set_ttysig,cancel_reset_ttysig, cancel_transient,cancel_clear) cancel_set_ttysig_f *cancel_set_ttysig; cancel_reset_ttysig_f *cancel_reset_ttysig; cancel_transient_f *cancel_transient; cancel_clear_f *cancel_clear; { SET_TTYSIG = cancel_set_ttysig; RESET_TTYSIG = cancel_reset_ttysig; TRANSIENT = cancel_transient; CLEAR = cancel_clear; } #define CANCEL_magic 0xF903 struct chancel_data { unsigned short magic; /* CANCEL_magic */ struct string *msg; VOLATILE int is_canceled; struct chancel_data * previous; } * new_cancel P_((const char * format, const char *msg, ...)); static struct chancel_data * VOLATILE current = NULL; #ifdef POSIX_SIGNALS static struct sigaction saved_state; static int state_set = 0; static void SA_HANDLER P_((int sig)); static void SA_HANDLER(sig) int sig; { SIGDPRINT(Debug,1,(&Debug,"Got SIGINT ...\n")); if (!current) { panic("CANCEL PANIC",__FILE__,__LINE__, "SA_HANDLER", "current pointer is not set",1); return; } if (CANCEL_magic != current->magic) panic("CANCEL PANIC",__FILE__,__LINE__, "SA_HANDLER", "Bad current pointer",1); current->is_canceled = 1; } #endif struct chancel_data * new_cancel ( #if ANSI_C const char * format, const char *msg, ... #else format,msg, va_alist #endif ) #if !ANSI_C CONST char * format; CONST char *msg; va_dcl #endif { va_list vl; struct string *store; struct chancel_data *ret; Va_start(vl, msg); /* defined in defs.h */ store = elm_smessage(160,format,msg,vl); va_end(vl); TRANSIENT(store); ret = safe_malloc(sizeof (*ret)); bzero((void *)ret,sizeof (*ret)); ret->magic = CANCEL_magic; ret->msg = store; ret->is_canceled = 0; ret->previous = NULL; if (current) { if (CANCEL_magic != current->magic) panic("CANCEL PANIC",__FILE__,__LINE__, "new_cancel", "Bad current pointer",0); ret->previous = current; } else { #ifdef POSIX_SIGNALS struct sigaction act; bzero((void *)&act,sizeof (act)); act.sa_handler = &SA_HANDLER; sigemptyset(&(act.sa_mask)); /* No signal to mask while in handler */ act.sa_flags = 0; #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; /* SunOS */ #endif state_set = 0; bzero((void *)&saved_state,sizeof (saved_state)); current = ret; if (0 == sigaction(SIGINT,&act,&saved_state)) { DPRINT(Debug,10,(&Debug,"SIGINT handler installed\n")); state_set = 1; } else { DPRINT(Debug,10,(&Debug,"Failed to set SIGINT handler\n")); } #endif SET_TTYSIG(); } current = ret; return ret; } int is_canceled(cd) struct chancel_data *cd; { int ret; if (CANCEL_magic != cd->magic) panic("CANCEL PANIC",__FILE__,__LINE__, "is_canceled", "Bad pointer (magic)",0); ret = cd->is_canceled; if (ret) { struct string * X = format_string(CATGETS(elm_msg_cat, MeSet, MeCanceled, "%S canceled"), cd->msg); TRANSIENT(X); free_string(&X); } return ret; } void free_cancel(cd) struct chancel_data **cd; { struct chancel_data *x = *cd; if (CANCEL_magic != x->magic) panic("CANCEL PANIC",__FILE__,__LINE__, "free_cancel", "Bad pointer (magic)",0); if (current != x) panic("CANCEL PANIC",__FILE__,__LINE__, "free_cancel", "pointer not current",0); if (x->previous && CANCEL_magic != x->previous->magic) panic("CANCEL PANIC",__FILE__,__LINE__, "free_cancel", "bad previous pointer",0); if (x->previous) { TRANSIENT(x->previous->msg); } else { RESET_TTYSIG(); CLEAR(); #ifdef POSIX_SIGNALS if (!state_set) { DPRINT(Debug,10,(&Debug,"SIGINT was not handler installed\n")); } else if (0 == sigaction(SIGINT,&saved_state,NULL)) { DPRINT(Debug,10,(&Debug,"SIGINT handler is reset\n")); } else { DPRINT(Debug,1,(&Debug,"failed to reset SIGINT handler\n")); } state_set = 0; #endif } current = x->previous; free_string (& (x->msg) ); x->magic = 0; free(x); x = NULL; *cd = x; } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */