示例#1
0
/* parse user command line */
static void parseargs(char *argstr, int *argc_p, char **argv, char** resid)
{
	char	c;


	argc = 0;

	/* tokenize the argstr */
	last_state = PS_WHITESPACE;

	while ((c = *argstr) != 0) {
		if (c == ';' && last_state != PS_STRING && last_state != PS_ESCAPE)
			break;

		if (last_state == PS_ESCAPE) {
			new_state = stacked_state;

		} else if (last_state == PS_STRING) {
			if (c == '"') {
				new_state = PS_WHITESPACE;
				*argstr   = 0;
			} else {
				new_state = PS_STRING;
			}

		} else if ((c == ' ') || (c == '\t')) {
			/* whitespace character */
			*argstr   = 0;
			new_state = PS_WHITESPACE;

		} else if (c == '"') {
			new_state = PS_STRING;
			*argstr++    = 0;
			argv[argc++] = argstr;

		} else if (c == '\\') {
			stacked_state = last_state;
			new_state     = PS_ESCAPE;

		} else {
			/* token */
			if (last_state == PS_WHITESPACE) {
				argv[argc++] = argstr;
			}
			new_state = PS_TOKEN;
		}

		last_state = new_state;
		argstr++;
	}

#if 0 /* for debugging */
	{
		int i;
		putLabeledWord("parseargs: argc=", argc);
		for (i = 0; i < argc; i++) {
			puts("   ");
			puts(argv[i]);
			puts("\r\n");
		}
	}
#endif
	
	argv[argc] = NULL;
	if (argc_p != NULL)
		*argc_p = argc;

	if (*argstr == ';') {
		*argstr++ = '\0';
	}
	*resid = argstr;
}
示例#2
0
/* Returns the length of the file received, or 0 on error: */
int ymodem_receive(char *buf, unsigned int length)
{
  unsigned char packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
  int packet_length, i, file_done, session_done, crc_tries, crc_nak, use_crc;
  unsigned int packets_received, errors, timeout, first_try = 1;
  char file_name[FILE_NAME_LENGTH], file_size[FILE_SIZE_LENGTH], *file_ptr;
  char *buf_ptr;
  unsigned long size = 0;
#ifdef CONFIG_MD5
  unsigned int sum[MD5_SUM_WORDS];
#endif

  if(crc16_init() < 0){
    putstr("Unable to generate CRC16 lookup table\r\n");
    return 0;
  }

  putstr("ready for YMODEM transfer...\r\n");

  /* Give the user time to frantically type in the file name: */
  timeout = INITIAL_TIMEOUT;

  for(session_done = 0, errors = 0; ; ){

    crc_tries = crc_nak = use_crc = 1;

    if(!first_try)
      putc(CRC);

    first_try = 0;

    for(packets_received = 0, file_done = 0, buf_ptr = buf; ; ){

      switch(receive_packet(packet_data, &packet_length, use_crc, timeout)){
      case 0:
	
	errors = 0;

	switch(packet_length){
	case -1:  /* abort */
	  
	  putc(ACK);
	  
	  return 0;
	  
	case 0:   /* end of transmission */
	  
	  putc(ACK);
	  
	  /* Should add some sort of sanity check on the number of
	   * packets received and the advertised file length.
	   */

	  file_done = 1;
	  
	  break;
	  
	default:  /* normal packet */
	  
	  if((packet_data[PACKET_SEQNO_INDEX] & 0xff) !=
	     (packets_received & 0xff)){

	    putc(NAK);
	    
	  } else {
	    
	    if(packets_received == 0){
	      
	      /* The spec suggests that the whole data section should
	       * be zeroed, but I don't think all senders do this. If
	       * we have a NULL filename and the first few digits of
	       * the file length are zero, we'll call it empty.
	       */
	      for(i = PACKET_HEADER; i < PACKET_HEADER + 4; ++i)
		if(packet_data[i] != 0)
		  break;

	      if(i < PACKET_HEADER + 4){  /* filename packet has data */

		for(file_ptr = packet_data + PACKET_HEADER, i = 0;
		    *file_ptr && i < FILE_NAME_LENGTH;)
		  file_name[i++] = *file_ptr++;
		
		file_name[i++] = '\0';
		
		for(++file_ptr, i = 0;
		    *file_ptr != ' ' && i < FILE_SIZE_LENGTH;)
		  file_size[i++] = *file_ptr++;
		
		file_size[i++] = '\0';

		size = strtoul(file_size, NULL, 0);
		
		if(size > length){
		  
		  putc(CAN);
		  putc(CAN);

		  delay_seconds(3);

		  putstr("Receive buffer too small (");
		  putHexInt32(length);
		  putLabeledWord(") to accept file size ", size);

		  return 0;

		}
		
		putc(ACK);
		putc(crc_nak ? CRC : NAK);

		crc_nak = 0;

	      } else {  /* filename packet is empty; end session */

		putc(ACK);

		file_done = 1;
		session_done = 1;

		break;

	      }
	      
	    } else {
	      
	      /* This shouldn't happen, but we check anyway in case the
	       * sender lied in its filename packet:
	       */
	      if((buf_ptr + packet_length) - buf > length){

		putc(CAN);
		putc(CAN);

		delay_seconds(3);

		putLabeledWord("Sender exceeded size of receive buffer: ",
			       length);

		return 0;

	      }

	      memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
	      
	      buf_ptr += packet_length;
	      
	      putc(ACK);

	    }
	    
	    ++packets_received;
	    
	  }  /* sequence number ok */
	  
	}
	
	break;
	
      default:

	if(++errors >= 
	   ((packets_received == 0 ? MAX_CRC_TRIES : 0) + MAX_ERRORS)){

	  putc(CAN);
	  putc(CAN);

	  delay_seconds(1);

	  putstr("Too many errors during receive; giving up.\r\n");

	  return 0;

	}

	if(packets_received == 0){

	  if(crc_tries < MAX_CRC_TRIES) {
	    ++crc_tries;
	    timeout = CRC_TIMEOUT;
	  } else {
	    crc_nak = use_crc = 0;
	    timeout = NAK_TIMEOUT;
	  }

	}

	putc(crc_nak ? CRC : NAK);

      }
      
      if(file_done)
	break;

    }  /* receive packets */

    if(session_done)
      break;

  }  /* receive files */

#ifdef CONFIG_MD5
  /* Give sender time to exit so that the subsequent MD5 display will be
   * visible on the user's terminal:
   */
  delay_seconds(1);

  md5_sum(buf, size, sum);
  md5_display(sum);
  putstr("  ");
  putstr(file_name);
  putstr("\r\n");
#endif
  
  return size;

}