/*{{{  #includes*/
#ifdef CONFIG_H
#   include "config.h"
#endif

#include <sys/types.h>
#include <errno.h>
#include <pwd.h>
#include <limits.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <local/bool.h>

#define SIGNALS_C
#define I_DISPLAY_C
#define I_FOLDFILING_C
#define I_FOLDING_C
#define I_GETMSG_C
#define I_GETTK_C
#define I_INIT_C
#define I_KEYBOARD_C
#define I_MAIN_C
#define I_MESSAGES_C
#define I_PROMPT_C
#define I_SCREEN_C
#define I_VIRTUAL_C

#include "exit.h"
#include "origami.h"
/*}}}  */

public unsigned char general_abort_key = 255;
private bool alarm_running=FALSE;
public int alarm_time = -1;

/*{{{  got_alarm*/
public void got_alarm(int sig)
{
  signal(SIGALRM,SIG_IGN);
  do_auto_save= (auto_save && alarm_running);
  interrupt_restore=TRUE;
  signal(SIGALRM,got_alarm);
}
/*}}}  */
/*{{{  set_alarm*/
public void set_alarm(int delay)
{
  alarm_running=TRUE;
  if (delay!=0) alarm_time=delay;
  if (alarm_time<MIN_ALARMTIME || alarm_time>MAX_ALARMTIME)
   { message((unsigned char*)M_ALARM,TRUE);alarm_time=NORM_ALARMTIME; }
  alarm(alarm_time*60);
}
/*}}}  */
/*{{{  reset_alarm*/
public void reset_alarm()
{
  alarm_running=FALSE;
  alarm(0);
}
/*}}}  */

/*{{{  enable_sig_abort*/
public void enable_sig_abort(void)
{
  if (general_abort_key==255) return;
  signal(SIGINT, ori_abort);
}
/*}}}  */
/*{{{  disable_sig_abort*/
public void disable_sig_abort(void)
{
  signal(SIGINT, SIG_IGN);
}
/*}}}  */

#ifdef SIGWINCH
/*{{{  window*/
private void window()
{
  signal(SIGWINCH,SIG_IGN);
  win_changed=TRUE;
  signal(SIGWINCH,window);
}
/*}}}  */
#endif

/*{{{  bktoshell           suspend Origami and wait to wake up*/
public void bktoshell(void)
{
#  ifdef _POSIX_JOB_CONTROL
     if (!no_suspend)
      { int pid;

        message(get_msg(M_SUSPEND),TRUE);
        reset_keyboard();
        reset_terminal();
        pid = getpid();
        kill(pid,SIGTSTP);
      }
     else
#  endif
        message(get_msg(M_NO_JOB),TRUE);
}
/*}}}  */
/*{{{  rtfrmshell          wake origami up*/
#ifdef _POSIX_JOB_CONTROL
public void rtfrmshell()
{
  init_terminal();
  init_keyboard();
  restore(1);
  title_op(CHGTITLE);
}
#endif
/*}}}  */

/*{{{  send me a mail concerning dumped file*/
#ifndef TOS
  private void mail_me(char *name)
  {
#    ifndef DOS
      /*{{{  variable declarations*/
      struct passwd *pw_entry;
      FILE *mail;
      char cmd[80], wdbuf[_POSIX_PATH_MAX+1], *wd=getcwd(wdbuf, _POSIX_PATH_MAX);
      /*}}}  */

      if ((wd=getcwd(wdbuf,_POSIX_PATH_MAX)) && (pw_entry=getpwuid(getuid())))
       { mail=popen(MAILCMD(cmd,(char*)get_msg(M_MAIL_S),pw_entry->pw_name),"w");
         if (mail)
          /*{{{  send mail*/
          { fputs((char*)get_msg(M_MAIL_1),mail);
            fputs((char*)get_msg(M_MAIL_2,
                                 real_tail==real_head?empty_text
                                                     :get_data(real_tail),
                                 wd,
                                 PATH_SEP,
                                 name),
                  mail);
            fputs((char*)get_msg(M_MAIL_3),mail);
            pclose(mail);
          }
          /*}}}  */
       }
#    endif
  }
#endif
/*}}}  */

/*{{{  exit_origami*/
public void exit_origami(RETURNS c, unsigned char *string)
{
  char name[_POSIX_PATH_MAX];
  static int exiting=0;

  /*{{{  maybe mail and dump*/
#  ifdef NOMEMDUMP
    free(mem_dump_malloc);
#  endif
  if (    !exiting++
       && file_changed
       && (    c==r_sig
            || c==r_ocl_err
            || c==r_tds_crash
            || c==r_eof
#           ifdef NOMEMDUMP
            || c==r_mem_full
#           endif
          )
  ) mail_me(dump_file(name));
  /*}}}  */
  /*{{{  end_data_handle*/
  if (end_data_handle())
   { oputc('\n');
     oputs((char *)get_msg(F_VM_FAIL,"access",strerror(errno)));
     c=r_vir_err;
   }
#  ifdef AUTOSAVE_FILE
     if (autosave_done) unlink(AUTOSAVE_FILE);
#  endif
  /*}}}  */
  if (string)
  {
    oputc('\n');
    oputs((char *)string);
  }
  close(msg_file);
  reset_terminal();
  reset_keyboard();
#  ifdef WINDOW_TITLE_CHANGE
     chg_w_title(w_title);
#  endif
  exit(c);
}
/*}}}  */

/*{{{  die_a_slow_death*/
private void die_a_slow_death(int sig)
{
  exit_origami(r_sig,(unsigned char *)0);
}
/*}}}  */

/*{{{  init_signals()*/
public void init_signals(void)
{
  signal(SIGTERM,die_a_slow_death);
  signal(SIGHUP,die_a_slow_death);
  signal(SIGQUIT,die_a_slow_death);
  signal(SIGALRM,got_alarm);
  signal(SIGPIPE,SIG_IGN);
#  ifdef SIGWINCH
     signal(SIGWINCH,window);
#  endif
  /*{{{  jobcontrol*/
#  ifdef _POSIX_JOB_CONTROL
    signal(SIGTSTP,SIG_DFL);               /* set signals so that we can */
    signal(SIGCONT,(void(*)())rtfrmshell); /* suspend & restart Origami */
#  endif
  /*}}}  */
  disable_abort();
}
/*}}}  */
