Beispiel #1
0
void
command_line_handler (char *rl)
{
  struct buffer *line_buffer = get_command_line_buffer ();
  struct ui *ui = current_ui;
  char *cmd;

  cmd = handle_line_of_input (line_buffer, rl, 1, "prompt");
  if (cmd == (char *) EOF)
    {
      /* stdin closed.  The connection with the terminal is gone.
	 This happens at the end of a testsuite run, after Expect has
	 hung up but GDB is still alive.  In such a case, we just quit
	 gdb killing the inferior program too.  */
      printf_unfiltered ("quit\n");
      execute_command ("quit", 1);
    }
  else if (cmd == NULL)
    {
      /* We don't have a full line yet.  Print an empty prompt.  */
      display_gdb_prompt ("");
    }
  else
    {
      ui->prompt_state = PROMPT_NEEDED;

      command_handler (cmd);

      if (ui->prompt_state != PROMPTED)
	display_gdb_prompt (0);
    }
}
Beispiel #2
0
static int process_req_vendor(struct udc *udc, struct usb_ctrlrequest *ctrl)
{
	if (ctrl->bRequest == 0x40)
		return command_handler(udc, ctrl);

	return -1;
}
static inline void dpram_ipc_rx(struct dpram_link_device *dpld, u16 intr)
{
	if (unlikely(INT_CMD_VALID(intr)))
		command_handler(dpld, intr);
	else
		non_command_handler(dpld, intr);
}
Beispiel #4
0
void msg_event_handler( int fd, int msgid, int event ) {
    char buf[PACK_DATA_SIZE];
    ssize_t n;
//	printf( "event 0x%03x for msg %d\n", event, msgid );
    switch ( event ) {
    case MSG_EVT_ACCEPT_READY:
        if ( msg_accept( fd, msgid ) != 0 )
            msg_set_read( fd, msgid );
        // These are commands
        break;
    case MSG_EVT_READ_READY:
        msg_clr_read( fd, msgid );

        n = msg_read( fd, msgid, buf, sizeof( buf ) );
        if ( n <= 0 ) {
            cleanup_connection( msg_get_type( fd, msgid ) );
            break;
        }

        if ( msg_get_type( fd, msgid ) < 0 ) {
            /* If the msgid is less than zero, it refers to a command and
               the message should not be routed to a file descriptor. */

            // the entire command must fit inside one transport
            command_handler( fd, msgid, buf, n );

        } else {
            zs_set_write( msg_get_type( fd, msgid ) );
            /* if msgid is zero or greater it refers to a socket file
               descriptor that the message should be routed to. */
            if ( zs_write( msg_get_type( fd, msgid ), buf, n ) == -1 )
                cleanup_connection( msg_get_type( fd, msgid ) );
        }
        break;
    case MSG_EVT_WRITE_READY:
        if ( msgid < 0 ) break;
        zs_set_read( msg_get_type( fd, msgid ) );
        msg_clr_write( fd, msgid );
        break;
    case MSG_SWITCH_EVT_IO_ERROR:
        //zclose( msg_switch->sockfd );
        if ( website_get_by_sockfd( fd ) )
            remove_website( fd );
        else {
            for ( n = 0; n < FD_SETSIZE; n++ ) {
                if ( msg_exists( fd, n ) ) {
                    if ( msg_get_type( fd, n ) > 0 )
                        cleanup_connection( msg_get_type( fd, n ) );
                    //	else
                    //		msg_close( fd, n );
                }
            }
            msg_switch_destroy( fd );
            zs_close( fd );
        }
        break;
    }
}
Beispiel #5
0
static irqreturn_t dpram_irq_handler(int irq, void *data)
{
	struct dpram_link_device *dpld = (struct dpram_link_device *)data;
	struct link_device *ld = (struct link_device *)&dpld->ld;
	u16 int2ap = 0;

	if (unlikely(ld->mode == LINK_MODE_OFFLINE))
		return IRQ_HANDLED;

	if (dpram_wake_up(dpld) < 0) {
		log_dpram_status(dpld);
		trigger_force_cp_crash(dpld);
		return IRQ_HANDLED;
	}

	int2ap = recv_intr(dpld);

	if (unlikely(int2ap == INT_POWERSAFE_FAIL)) {
		mif_info("%s: int2ap == INT_POWERSAFE_FAIL\n", ld->name);
		goto exit;
	} else if (int2ap == 0x1234 || int2ap == 0xDBAB || int2ap == 0xABCD) {
		if (dpld->ext_op && dpld->ext_op->dload_cmd_handler) {
			dpld->ext_op->dload_cmd_handler(dpld, int2ap);
			goto exit;
		}
	}

	if (unlikely(EXT_UDL_CMD(int2ap))) {
		if (likely(EXT_INT_VALID(int2ap))) {
			if (UDL_CMD_VALID(int2ap))
				udl_command_handler(dpld, int2ap);
			else if (EXT_CMD_VALID(int2ap))
				ext_command_handler(dpld, int2ap);
			else
				mif_info("%s: ERR! invalid intr 0x%04X\n",
					ld->name, int2ap);
		} else {
			mif_info("%s: ERR! invalid intr 0x%04X\n",
				ld->name, int2ap);
		}
	} else {
		if (likely(INT_VALID(int2ap))) {
			if (unlikely(INT_CMD_VALID(int2ap)))
				command_handler(dpld, int2ap);
			else
				non_command_handler(dpld, int2ap);
		} else {
			mif_info("%s: ERR! invalid intr 0x%04X\n",
				ld->name, int2ap);
		}
	}

exit:
	clear_intr(dpld);
	dpram_allow_sleep(dpld);
	return IRQ_HANDLED;
}
Beispiel #6
0
// handle one socket connection
int client_handler(int connfd) {

    int r = prompt(connfd);

    if(!r)  return CLIENT_END;

    if(r != COMMAND_HANDLED) {
        command_handler(connfd);
    }
    print_prompt_sign(connfd);
    return CLIENT_CONT;

}
Beispiel #7
0
static
void *
_server_socket_command_handler (void *arg) {
	thread_list_t entry = (thread_list_t)arg;
	accept_command_t clean = ACCEPT_THREAD_CLEAN;

	command_handler (entry->fd, entry->config);
	entry->stopped = 1;

	if (write (s_fd_accept_terminate[1], &clean, sizeof (clean)) == -1) {
		common_log (LOG_FATAL, "write failed");
	}

	return NULL;
}
Beispiel #8
0
/* ------------- entering return in command prompt */
G_MODULE_EXPORT void on_textEntry_Command_activate(
	GtkObject *object,
	gpointer user_data)
{
	char cmd_buffer[256];

	// copy it in
	strncpy(cmd_buffer, gtk_entry_get_text(GTK_ENTRY(object)), ARRAY_SIZE(cmd_buffer)-1);
	cmd_buffer[ARRAY_SIZE(cmd_buffer)-1]= 0;

	// clear it out..
	gtk_entry_set_text(GTK_ENTRY(object), "");

	/*only do something if a command was entered. Don't do anything if user just hit return*/
	if(strcspn(cmd_buffer," ,\n\t"))
	{
		/* remember it */
		record_command(cmd_buffer);

		/* call cmd multiplexor  */
		command_handler(cmd_buffer);
	}
}
Beispiel #9
0
int main()
{
	int flags = fcntl(0, F_GETFL, 0);
	fcntl(0, F_SETFL, flags | O_NONBLOCK);
	char buffer[1024];

	getcwd(directory, 1024);

	List* l = list_constructor();
	command_t command;
	reset_command(&command);

	prompt();
	while(1)
	{
		if(read(0, buffer, 1023) > 0)
		{
			// read the command into the struct
			read_command(buffer, &command);
			// parse the command for background execution, change directory, or file redirection
			parse_command(&command);
			/* call the command handler.
			   this will execute the command. handles both background and non-background
			*/
			int pid = command_handler(&command, l);
	 		if(pid == 0)
	 		{
	 			return 0;
	 		}
			// reset the command.
			reset_command(&command);
		}
		// check for background commands and remove them from the wait list.
		check_background_commands(l);
	}
	return 0;
}
Beispiel #10
0
/* NOTE: 1999-04-30 This is the asynchronous version of the
   command_line_input function; command_line_input will become
   obsolete once we use the event loop as the default mechanism in
   GDB.  */
static void
command_line_handler (char *rl)
{
  static char *linebuffer = 0;
  static unsigned linelength = 0;
  char *p;
  char *p1;
  char *nline;
  int repeat = (instream == stdin);

  if (annotation_level > 1 && instream == stdin)
    {
      printf_unfiltered (("\n\032\032post-"));
      puts_unfiltered (async_annotation_suffix);
      printf_unfiltered (("\n"));
    }

  if (linebuffer == 0)
    {
      linelength = 80;
      linebuffer = (char *) xmalloc (linelength);
    }

  p = linebuffer;

  if (more_to_come)
    {
      strcpy (linebuffer, readline_input_state.linebuffer);
      p = readline_input_state.linebuffer_ptr;
      xfree (readline_input_state.linebuffer);
      more_to_come = 0;
    }

#ifdef STOP_SIGNAL
  if (job_control)
    signal (STOP_SIGNAL, handle_stop_sig);
#endif

  /* Make sure that all output has been output.  Some machines may let
     you get away with leaving out some of the gdb_flush, but not
     all.  */
  wrap_here ("");
  gdb_flush (gdb_stdout);
  gdb_flush (gdb_stderr);

  if (source_file_name != NULL)
    ++source_line_number;

  /* If we are in this case, then command_handler will call quit 
     and exit from gdb.  */
  if (!rl || rl == (char *) EOF)
    {
      command_handler (0);
      return;			/* Lint.  */
    }
  if (strlen (rl) + 1 + (p - linebuffer) > linelength)
    {
      linelength = strlen (rl) + 1 + (p - linebuffer);
      nline = (char *) xrealloc (linebuffer, linelength);
      p += nline - linebuffer;
      linebuffer = nline;
    }
  p1 = rl;
  /* Copy line.  Don't copy null at end.  (Leaves line alone
     if this was just a newline).  */
  while (*p1)
    *p++ = *p1++;

  xfree (rl);			/* Allocated in readline.  */

  if (p > linebuffer && *(p - 1) == '\\')
    {
      *p = '\0';
      p--;			/* Put on top of '\'.  */

      readline_input_state.linebuffer = xstrdup (linebuffer);
      readline_input_state.linebuffer_ptr = p;

      /* We will not invoke a execute_command if there is more
	 input expected to complete the command.  So, we need to
	 print an empty prompt here.  */
      more_to_come = 1;
      display_gdb_prompt ("");
      return;
    }

#ifdef STOP_SIGNAL
  if (job_control)
    signal (STOP_SIGNAL, SIG_DFL);
#endif

#define SERVER_COMMAND_LENGTH 7
  server_command =
    (p - linebuffer > SERVER_COMMAND_LENGTH)
    && strncmp (linebuffer, "server ", SERVER_COMMAND_LENGTH) == 0;
  if (server_command)
    {
      /* Note that we don't set `line'.  Between this and the check in
         dont_repeat, this insures that repeating will still do the
         right thing.  */
      *p = '\0';
      command_handler (linebuffer + SERVER_COMMAND_LENGTH);
      display_gdb_prompt (0);
      return;
    }

  /* Do history expansion if that is wished.  */
  if (history_expansion_p && instream == stdin
      && ISATTY (instream))
    {
      char *history_value;
      int expanded;

      *p = '\0';		/* Insert null now.  */
      expanded = history_expand (linebuffer, &history_value);
      if (expanded)
	{
	  /* Print the changes.  */
	  printf_unfiltered ("%s\n", history_value);

	  /* If there was an error, call this function again.  */
	  if (expanded < 0)
	    {
	      xfree (history_value);
	      return;
	    }
	  if (strlen (history_value) > linelength)
	    {
	      linelength = strlen (history_value) + 1;
	      linebuffer = (char *) xrealloc (linebuffer, linelength);
	    }
	  strcpy (linebuffer, history_value);
	  p = linebuffer + strlen (linebuffer);
	}
      xfree (history_value);
    }

  /* If we just got an empty line, and that is supposed to repeat the
     previous command, return the value in the global buffer.  */
  if (repeat && p == linebuffer && *p != '\\')
    {
      command_handler (saved_command_line);
      display_gdb_prompt (0);
      return;
    }

  for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++);
  if (repeat && !*p1)
    {
      command_handler (saved_command_line);
      display_gdb_prompt (0);
      return;
    }

  *p = 0;

  /* Add line to history if appropriate.  */
  if (instream == stdin
      && ISATTY (stdin) && *linebuffer)
    add_history (linebuffer);

  /* Note: lines consisting solely of comments are added to the command
     history.  This is useful when you type a command, and then
     realize you don't want to execute it quite yet.  You can comment
     out the command and then later fetch it from the value history
     and remove the '#'.  The kill ring is probably better, but some
     people are in the habit of commenting things out.  */
  if (*p1 == '#')
    *p1 = '\0';			/* Found a comment.  */

  /* Save into global buffer if appropriate.  */
  if (repeat)
    {
      if (linelength > saved_command_line_size)
	{
	  saved_command_line = xrealloc (saved_command_line, linelength);
	  saved_command_line_size = linelength;
	}
      strcpy (saved_command_line, linebuffer);
      if (!more_to_come)
	{
	  command_handler (saved_command_line);
	  display_gdb_prompt (0);
	}
      return;
    }

  command_handler (linebuffer);
  display_gdb_prompt (0);
  return;
}
Beispiel #11
0
/*******************************************************************
 * MAIN()
 *******************************************************************/
int
main(void)
{
	long lEEPROMRetStatus;
	uint16_t i=0;
	uint8_t halted_latch = 0;

	// Set the clocking to run at 80 MHz from the PLL.
	// (Well we were at 80MHz with SYSCTL_SYSDIV_2_5 but according to the errata you can't
	// write to FLASH at frequencies greater than 50MHz so I slowed it down. I supposed we
	// could slow the clock down when writing to FLASH but then we need to find out how long
	// it takes for the clock to stabilize. This is on at the bottom of my list of things to do
	// for now)
	SysCtlClockSet(SYSCTL_SYSDIV_4_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

	// Initialize the device pinout.
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);

	// Enable processor interrupts.
	IntMasterEnable();

	// Setup the UART's
	my_uart_0_init(115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
	// command_handler_init overwrites the baud rate. We still need to configure the pins though
	my_uart_1_init(38400, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

	// Enable the command handler
	command_handler_init(); // We set the baud in here

	// Start the timers
	my_timer0_init();
	my_timer1_init();

	i2c_init();
	motor_init();
	qei_init();
	gyro_init();
	accel_init();
	led_init();
	//rc_radio_init();
	//setupBluetooth();

	// Initialize the EEPROM emulation region.
	lEEPROMRetStatus = SoftEEPROMInit(EEPROM_START_ADDR, EEPROM_END_ADDR, EEPROM_PAGE_SIZE);
	if(lEEPROMRetStatus != 0) UART0Send("EEprom ERROR!\n", 14);

#if 0
	// If ever we wanted to write some parameters to FLASH without the HMI
	// we could do it here.
	SoftEEPROMWriteDouble(kP_ID, 10.00);
	SoftEEPROMWriteDouble(kI_ID, 10.00);
	SoftEEPROMWriteDouble(kD_ID, 10.00);
	SoftEEPROMWriteDouble(ANG_ID, 0.0);
	SoftEEPROMWriteDouble(COMPC_ID, 0.99);
#endif

	kP = SoftEEPROMReadDouble(kP_ID);
	kI = SoftEEPROMReadDouble(kI_ID);
	kD = SoftEEPROMReadDouble(kD_ID);
	commanded_ang = zero_ang = SoftEEPROMReadDouble(ANG_ID);
	COMP_C = SoftEEPROMReadDouble(COMPC_ID);

	pid_init(kP, kI, kD, &pid_ang);
	motor_controller_init(20, 100, 10, &mot_left);
	motor_controller_init(20, 100, 10, &mot_right);


	//pid_init(0.0, 0.0, 0.0, &pid_pos_left);
	//pid_init(0.0, 0.0, 0.0, &pid_pos_right);

	//UART0Send("Hello World!\n", 13);

	// Tell the HMI what the initial parameters are.
	print_params(1);


	while(1)
	{
		delta_t = myTimerValueGet();
		myTimerZero();
		sum_delta_t += delta_t;

		// Read our sensors
		accel_get_xyz_cal(&accel_x, &accel_y, &accel_z, true);
		gyro_get_y_cal(&gyro_y, false);

		// Calculate the pitch angle with the accelerometer only
		R = sqrt(pow(accel_x, 2) + pow(accel_z, 2));
		accel_pitch_ang = (acos(accel_z / R)*(RAD_TO_DEG)) - 90.0 - zero_ang;
		//accel_pitch_ang = (double)((atan2(accel_x, -accel_z))*RAD_TO_DEG - 90.0);

		gyro_pitch_ang += (double)gyro_y*g_gyroScale*CONV_TO_SEC(delta_t);

		// Kalman filter
		//filtered_ang = kalman((double)accel_pitch_ang, ((double)gyro_y)*g_gyroScale, CONV_TO_SEC(delta_t));
		filtered_ang = (COMP_C*(filtered_ang+((double)gyro_y*g_gyroScale*CONV_TO_SEC(delta_t)))) + ((1.0-COMP_C)*(double)accel_pitch_ang);

		// Skip the rest of the process until the angle stabilizes
		if(i < 250) { i++; continue; }

		// Tell the HMI what's going on every 100ms
		if(sum_delta_t >= 1000)
		{
			print_update(1);
			print_debug(0);
			//print_control_surfaces(0);
			led_toggle();
			//print_angle();
			sum_delta_t = 0;
		}


		// See if the HMI has anything to say
		command_handler();
		//continue;

		// If we are leaning more than +/- FALL_ANG deg off center it's hopeless.
		// Turn off the motors in hopes of some damage control
		if( abs(filtered_ang) > FALL_ANG )
		{
			if(halted_latch) continue;
			stop_motors();
			halted_latch = 1;
			continue;
		}
		halted_latch = 0;

		motor_val = pid_controller(calc_commanded_angle(0), filtered_ang, delta_t, &pid_ang);
		motor_left = motor_right = motor_val;
		drive_motors(motor_left*left_mot_gain, motor_right*right_mot_gain);
	}
}
Beispiel #12
0
int main(void)
{
	// init all needed services
	cli();
	timer_init();
	USART_init();
	ADC_init();
	sei(); 
	
	// set up enable port
	ENA_DDR = /*(1 << ENA_LED) |*/ (1 << ENA_PIN);
//	ENA_PORT = (1 << ENA_LED);
	
	// init condition is receiving
	driverReceive();
	
	// string, char and ascii buffers for serial comm.
	uint8_t read_buf = 0x00, ascii_bufh = 0x00, ascii_bufl = 0x00;
	char str_buf[10];
	
	// send own address on startup
	HexToAscii(str_buf, 3, own_addr);
	sendString(str_buf);
	sendString(EOM);
	
    while(1) {
		// check if there is something to be read (non blocking...)
		if ( USART_dataAvaliable() ){
			read_buf = 0x00;
			read_buf = USART_readByte();
			switch(MPPC_status){
				
				/* no start delimiter, awaits start delimiter */
				
				case IDLE:
				if (read_buf == '<'){
					MPPC_status = LISTENING;
				} else {
					MPPC_status = IDLE;
					sleep_ms(2);
				}
				break;
	
				/* received a start delimiter, awaits adress */
				
				case LISTENING:
				// check wether there are characters or ASCII numbers beeing send
				if ( ((read_buf >= '0') && (read_buf <= '9')) ||
				((read_buf >= 'A') && (read_buf <= 'F')) ) {
					// a ASCII number has been sent, we need another digit
					str_buf[0] = read_buf;
					str_buf[1] = USART_receiveByte();
					// convert both ascii numbers into a 'real' hex number
					read_buf = AsciiToHex(str_buf, 2);
					HexToAscii(str_buf, 3, read_buf);
				} else {
					// in this stage we need an address; if there are no numbers beeing sent, we are not interested anymore!
					MPPC_status = IDLE;
					break;
				}
				// We received an address, converted it to hex and now want to check, if it is our's
				if (read_buf == own_addr){
					MPPC_status = ADDRESSED;
					// SEL_LED on -> module has been selected + echo
					sendString(str_buf);
//					ENA_PORT&= ~(1 << ENA_LED);
					// echo in ASCII
				} else {
					MPPC_status = IDLE;
				}
				break;

				/* received it's own address, awaits command */
				
				case ADDRESSED:
				if (read_buf == '>'){	// stop delimiter
					MPPC_status = IDLE;
//					ENA_PORT |= (1 << ENA_LED);	// SEL_LED off -> module has been deselected
				} else {
					command_handler(read_buf);	// yet another switch/case stucture...
				}
				break;

			} // end switch

		} // end if
		
		// apply bias voltages
		setBiasVoltage();
	}
}
Beispiel #13
0
void key_handler() {
    char c, i;
    while(true) {
        draw();
        c = G_wait_key();
        i = c - 48; //Convert ASCII character codes to digits
        if (i > 0 && i <= num_objs) {
            printf("Switching control to shape %d\n", i);
            obj = &objs[i-1];
        }
        switch (c) {
        case 84:
            //Down arrow key
            object3d_rotate(obj, -M_PI/60, 0, 0);
            break;
        case 82:
            //Up arrow key
            object3d_rotate(obj, M_PI/60, 0, 0);
            break;
        case 81:
            //Left arrow key
            object3d_rotate(obj, 0, M_PI/60, 0);
            break;
        case 83:
            //Right arrow key
            object3d_rotate(obj, 0, -M_PI/60, 0);
            break;
        case 'w':
            transform_object3d(obj, y_plus);
            break;
        case 'a':
            transform_object3d(obj, x_minus);
            break;
        case 's':
            transform_object3d(obj, y_minus);
            break;
        case 'd':
            transform_object3d(obj, x_plus);
            break;
        case 'q':
            transform_object3d(obj, z_minus);
            break;
        case 'e':
            transform_object3d(obj, z_plus);
            break;
        case ']':
            object3d_scale(obj, 1.1, 1.1, 1.1);
            break;
        case '[':
            object3d_scale(obj, 1.0/1.1, 1.0/1.1, 1.0/1.1);
            break;
        case '=':
            //viewdistance += .2;
            break;
        case '-':
            //viewdistance -= .2;
            break;
        case '+':
            //Smaller FOV zooms in
            fov -= M_PI/36;
            break;
        case '_':
            //Larger FOV zooms out
            fov += M_PI/36;
            break;
        case 32:
            command_handler();
            break;
        }
    }
}
Beispiel #14
0
int main (int argc, char *argv[])
{
	enum {
		OPT_SERVER,
		OPT_MUTLI_SERVER,
		OPT_DAEMON,
		OPT_VERBOSE,
		OPT_QUIET,
		OPT_SH,
		OPT_CSH,
		OPT_OPTIONS,
		OPT_NO_DETACH,
		OPT_LOG_FILE,
		OPT_VERSION,
		OPT_HELP
	};

	static struct option long_options[] = {
		{ "server", no_argument, NULL, OPT_SERVER },
		{ "multi-server", no_argument, NULL, OPT_MUTLI_SERVER },
		{ "daemon", no_argument, NULL, OPT_DAEMON },
		{ "verbose", no_argument, NULL, OPT_VERBOSE },
		{ "quiet", no_argument, NULL, OPT_QUIET },
		{ "sh", no_argument, NULL, OPT_SH },
		{ "csh", no_argument, NULL, OPT_CSH },
		{ "options", required_argument, NULL, OPT_OPTIONS },
		{ "no-detach", no_argument, NULL, OPT_NO_DETACH },
		{ "log-file", required_argument, NULL, OPT_LOG_FILE },
		{ "version", no_argument, NULL, OPT_VERSION },
		{ "help", no_argument, NULL, OPT_HELP },
		{ NULL, 0, NULL, 0 }
	};
	int long_options_ret;
	int base_argc = 1;

	int usage_ok = 1;
	enum {
		RUN_MODE_NONE,
		RUN_MODE_SERVER,
		RUN_MODE_MULTI_SERVER,
		RUN_MODE_DAEMON
	} run_mode = RUN_MODE_NONE;
	int env_is_csh = 0;
	int log_verbose = 0;
	int log_quiet = 0;
	int no_detach = 0;
	char *config_file = NULL;
	char *log_file = NULL;
	char *home_dir = NULL;
	int have_at_least_one_provider=0;
	FILE *fp_log = NULL;
	int i;
	CK_RV rv;

	dconfig_data_t config;

	const char * CONFIG_SUFFIX = ".conf";
	char *default_config_file = NULL;

#if !defined(HAVE_W32_SYSTEM)
	s_parent_pid = getpid ();
#endif

	if ((default_config_file = (char *)malloc (strlen (PACKAGE)+strlen (CONFIG_SUFFIX)+1)) == NULL) {
		common_log (LOG_FATAL, "malloc failed");
	}
	sprintf (default_config_file, "%s%s", PACKAGE, CONFIG_SUFFIX);

	common_set_log_stream (stderr);

	while ((long_options_ret = getopt_long (argc, argv, "vqsc", long_options, NULL)) != -1) {
		base_argc++;

		switch (long_options_ret) {
			case OPT_SERVER:
				run_mode = RUN_MODE_SERVER;
			break;
			case OPT_MUTLI_SERVER:
				run_mode = RUN_MODE_MULTI_SERVER;
			break;
			case OPT_DAEMON:
				run_mode = RUN_MODE_DAEMON;
			break;
			case OPT_VERBOSE:
			case 'v':
				log_verbose = 1;
			break;
			case OPT_QUIET:
			case 'q':
				log_quiet = 1;
			break;
			case OPT_SH:
			case 's':
			break;
			case OPT_CSH:
			case 'c':
				env_is_csh = 1;
			break;
			case OPT_OPTIONS:
				base_argc++;
				config_file = strdup (optarg);
			break;
			case OPT_NO_DETACH:
				no_detach = 1;
			break;
			case OPT_LOG_FILE:
				base_argc++;
				log_file = strdup (optarg);
			break;
			case OPT_VERSION:
				printf (
					"%s %s\n"
					"\n"
					"Copyright (c) 2006-2007 Zeljko Vrba <*****@*****.**>\n"
					"Copyright (c) 2006-2011 Alon Bar-Lev <*****@*****.**>\n"
					"\n"
					"This is free software; see the source for copying conditions.\n"
					"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
					PACKAGE,
					PACKAGE_VERSION
				);
				exit (1);
			break;
			case OPT_HELP:
				usage_ok = 0;
			break;
			default:
				usage_ok = 0;
			break;
		}
	}

	if (base_argc < argc) {
		if (!strcmp (argv[base_argc], "--")) {
			base_argc++;
		}
	}

	if (!usage_ok) {
		usage (argv[0]);
	}

	if (run_mode == RUN_MODE_NONE) {
		common_log (LOG_FATAL, "please use the option `--daemon' to run the program in the background");
	}

#if defined(HAVE_W32_SYSTEM)
	if (run_mode == RUN_MODE_DAEMON) {
		common_log (LOG_FATAL, "daemon mode is not supported");
	}
#endif

	home_dir = get_home_dir ();

	if (config_file == NULL) {
		if ((config_file = (char *)malloc (strlen (home_dir) + strlen (default_config_file)+2)) == NULL) {
			common_log (LOG_FATAL, "malloc failed");
		}
		sprintf (config_file, "%s%c%s", home_dir, CONFIG_PATH_SEPARATOR, default_config_file);
	}

	if (
		!dconfig_read (config_file, &config) &&
		!dconfig_read (CONFIG_SYSTEM_CONFIG, &config)
	) {
		common_log (LOG_FATAL, "Cannot open configuration file");
	}

	if (log_file != NULL) {
		if (config.log_file != NULL) {
			free (config.log_file);
		}
		if ((config.log_file = strdup (log_file)) == NULL) {
			common_log (LOG_FATAL, "strdup failed");
		}
	}

	if (log_verbose) {
		config.verbose = 1;
	}

#if !defined(HAVE_W32_SYSTEM)
	signal (SIGPIPE, SIG_IGN);
	signal (SIGINT, on_signal);
	signal (SIGTERM, on_signal);
	signal (SIGABRT, on_signal);
	signal (SIGHUP, on_signal);
#endif

	if (log_file != NULL) {
		if (strcmp (log_file, "stderr")) {
			if ((fp_log = fopen (log_file, "a")) != NULL) {
				common_set_log_stream (fp_log);
			}
		}
	}
	else if (config.log_file != NULL) {
		if (strcmp (config.log_file, "stderr")) {
			if ((fp_log = fopen (config.log_file, "a")) != NULL) {
				common_set_log_stream (fp_log);
			}
		}
	}

	if (config.debug) {
		common_log (LOG_DEBUG, "version: %s", PACKAGE_VERSION);
		dconfig_print (&config);
		common_log (LOG_DEBUG, "run_mode: %d", run_mode);
		common_log (LOG_DEBUG, "crypto: %s",
#if defined(ENABLE_OPENSSL)
			"openssl"
#elif defined(ENABLE_GNUTLS)
			"gnutls"
#else
			"invalid"
#endif
		);
	}

#if !defined(HAVE_W32_SYSTEM)
	if (run_mode == RUN_MODE_DAEMON || run_mode == RUN_MODE_MULTI_SERVER) {
		server_socket_create_name ();
	}

	/*
	 * fork before doing PKCS#11 stuff
	 * some providers don't behave well
	 */
	if (run_mode == RUN_MODE_DAEMON) {
		pid_t pid;

		pid = fork ();

		if (pid == -1) {
			common_log (LOG_FATAL, "fork failed");
		}

		if (pid != 0) {
			static const char *key = "SCDAEMON_INFO";
			char env[1024];
			snprintf (env, sizeof (env), "%s:%lu:1", s_socket_name, (unsigned long)pid);

			if (argc - base_argc > 0) {
				setenv(key, env, 1);
				execvp (argv[base_argc], &(argv[base_argc]));
				kill (pid, SIGTERM);
				exit (1);
			}
			else {
				if (env_is_csh) {
					*strchr (env, '=') = ' ';
					printf ("setenv %s %s\n", key, env);
				}
				else {
					printf ("%s=%s; export %s\n", key, env, key);
				}
				exit (0);
			}
		}

		if (!no_detach) {
			int i;

			for (i=0;i<3;i++) {
				if (fileno (common_get_log_stream ()) != i) {
					close (i);
				}
			}

			if (setsid () == -1) {
				common_log (LOG_FATAL, "setsid failed");
			}
		}

		if (chdir ("/") == -1) {
			common_log (LOG_FATAL, "chdir failed");
		}

		if (argc - base_argc > 0) {
			struct sigaction sa;

			memset (&sa, 0, sizeof (sa));
			sigemptyset (&sa.sa_mask);
#if defined(SA_INTERRUPT)
			sa.sa_flags |= SA_INTERRUPT;
#endif
			sa.sa_handler = on_alarm;
			sigaction (SIGALRM, &sa, NULL);
			alarm (10);
		}
	}
#endif				/* HAVE_W32_SYSTEM */

	assuan_set_assuan_log_prefix (PACKAGE);
	assuan_set_assuan_log_stream (common_get_log_stream ());

#if defined(USE_GNUTLS)
	if (gnutls_global_init () != GNUTLS_E_SUCCESS) {
		common_log (LOG_FATAL, "Cannot initialize gnutls");
	}
#endif

	if ((rv = pkcs11h_initialize ()) != CKR_OK) {
		common_log (LOG_FATAL, "Cannot initialize PKCS#11: %s", pkcs11h_getMessage (rv));
	}

	pkcs11h_setLogLevel (config.verbose ? PKCS11H_LOG_DEBUG2 : PKCS11H_LOG_INFO);
	pkcs11h_setLogHook (pkcs11_log_hook, NULL);
	pkcs11h_setTokenPromptHook (pkcs11_token_prompt_hook, NULL);
	pkcs11h_setPINPromptHook (pkcs11_pin_prompt_hook, NULL);
	pkcs11h_setProtectedAuthentication (TRUE);

	for (i=0;i<DCONFIG_MAX_PROVIDERS;i++) {
		if (
			config.providers[i].name != NULL &&
			config.providers[i].library != NULL
		) {
			if (
				(rv = pkcs11h_addProvider (
					config.providers[i].name,
					config.providers[i].library,
					config.providers[i].allow_protected,
					config.providers[i].private_mask,
					PKCS11H_SLOTEVENT_METHOD_POLL,
					0,
					config.providers[i].cert_is_private
				)) != CKR_OK
			) {
				common_log (LOG_WARNING, "Cannot add PKCS#11 provider '%s': %ld-'%s'", config.providers[i].name, rv, pkcs11h_getMessage (rv));
			}
			else {
				have_at_least_one_provider = 1;
			}
		}
	}

	if (!have_at_least_one_provider) {
		common_log (LOG_FATAL, "Could not load any provider");
	}

#if defined(HAVE_W32_SYSTEM)
	command_handler (-1, &config);
#else
{
	pthread_t accept_thread = 0;
	int accept_socket = -1;

	if (run_mode == RUN_MODE_DAEMON || run_mode == RUN_MODE_MULTI_SERVER) {
		accept_socket = server_socket_create ();

		server_socket_accept (accept_socket, &accept_thread, &config);
	}

	if (run_mode == RUN_MODE_DAEMON) {
		/*
		 * Emulate assuan behavior
		 */
		int fds[2];
		char c;
		if (pipe (fds)==-1) {
			common_log (LOG_FATAL, "Could not create pipe");
		}
		close (0);
		dup2 (fds[0], 0);
		close (fds[0]);
		while (read (0, &c, 1) == -1 && errno == EINTR);
		close (fds[1]);
	}
	else {
		command_handler (-1, &config);
	}

	if (run_mode == RUN_MODE_DAEMON || run_mode == RUN_MODE_MULTI_SERVER) {
		server_socket_accept_terminate (accept_thread);
		server_socket_close (accept_socket);
	}
}
#endif

	pkcs11h_terminate ();

#if defined(USE_GNUTLS)
	gnutls_global_deinit ();
#endif

	dconfig_free (&config);

	if (log_file != NULL) {
		free (log_file);
		log_file = NULL;
	}

	if (config_file != NULL) {
		free (config_file);
		config_file = NULL;
	}

	if (default_config_file != NULL) {
		free (default_config_file);
		default_config_file = NULL;
	}

	if (home_dir != NULL) {
		free (home_dir);
		home_dir = NULL;
	}

	if (fp_log != NULL) {
		fclose (fp_log);
		fp_log = NULL;
	}

	return 0;
}