Esempio n. 1
0
int sleepkick_main(int argc UNUSED_PARAM, char **argv)
{
	unsigned duration;
	unsigned watchdog;
	++argv;
	if (!*argv)
		bb_show_usage();
	duration = xatou(*argv);
	++argv;

	if(*argv)
	{ 
		int fd;         /* File handler for watchdog */
		int i = 0;
		int iMax = 0;

		watchdog =  xatou(*argv);
		iMax =   (int) (duration / watchdog);

		int modDuration = 0;
		int wReminder = 0;
		if( duration >= watchdog)
		{
			modDuration =   duration % watchdog;
		}
		else {
			modDuration  = duration;
		}

		fd = open(WATCHDOGDEV, O_RDWR);
		for( i = 0; i < iMax; i++)
		{
			write(fd, "1", 1);
			sleep(watchdog);	
		}
		if(modDuration)
		{
			write(fd, "1", 1);
			sleep(modDuration);
			write(fd, "1", 1);
		}
 		close(fd);
	}
	else 
	{
		sleep(duration);
	}
	return EXIT_SUCCESS;
}
Esempio n. 2
0
File: xatonum.c Progetto: rplnt/abrt
int xatoi_positive(const char *numstr)
{
    unsigned r = xatou(numstr);
    if (r > (unsigned)INT_MAX)
        error_msg_and_die("invalid number '%s'", numstr);
    return r;
}
Esempio n. 3
0
/*

   Process the 'config threshold: memcap #bytes, option2-name option2-value, ...'

   config threshold: memcap #bytes
*/
void ProcessThresholdOptions(char *options)
{
      int     i = 0;
      char ** args;
      int     nargs;
      char ** oargs;
      int     noargs;
      
      if( !s_enabled )
          return ;

      args = mSplit(options,",",10,&nargs,0);  /* get rule option pairs */

      for(i=0;i<nargs;i++)
      {
          oargs = mSplit(options," ",2,&noargs,0);  /* get rule option pairs */

          if( strcmp(oargs[0],"memcap") == 0  )
          {
             s_memcap = xatou(oargs[1],"config threshold: memcap");
          }
          else
          {
             FatalError("Threshold-RuleOptionParse: unknown argument\n");
          }
     }
     mSplitFree(&args, nargs);
     mSplitFree(&oargs, noargs);
}
Esempio n. 4
0
static tcflag_t *mode_type_flag(unsigned type, const struct termios *mode)
{
    static const uint8_t tcflag_offsets[] ALIGN1 = {
        offsetof(struct termios, c_cflag), /* control */
        offsetof(struct termios, c_iflag), /* input */
        offsetof(struct termios, c_oflag), /* output */
        offsetof(struct termios, c_lflag)  /* local */
    };

    if (type <= local) {
        return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]);
    }
    return NULL;
}

static void set_speed_or_die(enum speed_setting type, const char *arg,
                             struct termios *mode)
{
    speed_t baud;

    baud = tty_value_to_baud(xatou(arg));

    if (type != output_speed) {     /* either input or both */
        cfsetispeed(mode, baud);
    }
    if (type != input_speed) {      /* either output or both */
        cfsetospeed(mode, baud);
    }
}
Esempio n. 5
0
int halt_main(int argc, char **argv)
{
	static const int magic[] = {
#ifdef RB_HALT_SYSTEM
RB_HALT_SYSTEM,
#elif defined RB_HALT
RB_HALT,
#endif
#ifdef RB_POWER_OFF
RB_POWER_OFF,
#elif defined RB_POWERDOWN
RB_POWERDOWN,
#endif
RB_AUTOBOOT
	};
	static const int signals[] = { SIGUSR1, SIGUSR2, SIGTERM };

	char *delay;
	int which, flags, rc = 1;

	/* Figure out which applet we're running */
	for (which = 0; "hpr"[which] != *applet_name; which++);

	/* Parse and handle arguments */
	flags = getopt32(argv, "d:nf", &delay);
	if (flags & 1) sleep(xatou(delay));
	if (!(flags & 2)) sync();

	/* start of y42304 20080419: 解决96358芯片软复位问题:*/
#if defined(SUPPORT_BCM96358) || defined(SUPPORT_BCM96368)
	BSP_SYS_SoftReboot();
	return 0;
#endif
	/* end of y42304 20080419: 解决96358芯片软复位问题:*/

	/* Perform action. */
	if (ENABLE_INIT && !(flags & 4)) {
		if (ENABLE_FEATURE_INITRD) {
			pid_t *pidlist = find_pid_by_name("linuxrc");
			if (pidlist[0] > 0)
				rc = kill(pidlist[0], signals[which]);
			if (ENABLE_FEATURE_CLEAN_UP)
				free(pidlist);
		}
		if (rc)
			rc = kill(1, signals[which]);
	} 
	else
	{   
		rc = reboot(magic[which]);
	}

	if (rc)
		bb_error_msg("no");
	return rc;
}
Esempio n. 6
0
int vconfig_main(int argc, char **argv)
{
	struct vlan_ioctl_args ifr;
	const char *p;
	int fd;

	if (argc < 3) {
		bb_show_usage();
	}

	/* Don't bother closing the filedes.  It will be closed on cleanup. */
	/* Will die if 802.1q is not present */
	xopen(conf_file_name, O_RDONLY);

	memset(&ifr, 0, sizeof(struct vlan_ioctl_args));

	++argv;
	p = xfind_str(cmds+2, *argv);
	ifr.cmd = *p;
	if (argc != p[-1]) {
		bb_show_usage();
	}

	if (ifr.cmd == SET_VLAN_NAME_TYPE_CMD) { /* set_name_type */
		ifr.u.name_type = *xfind_str(name_types+1, argv[1]);
	} else {
		if (strlen(argv[1]) >= IF_NAMESIZE) {
			bb_error_msg_and_die("if_name >= %d chars", IF_NAMESIZE);
		}
		strcpy(ifr.device1, argv[1]);
		p = argv[2];

		/* I suppose one could try to combine some of the function calls below,
		 * since ifr.u.flag, ifr.u.VID, and ifr.u.skb_priority are all same-sized
		 * (unsigned) int members of a unions.  But because of the range checking,
		 * doing so wouldn't save that much space and would also make maintainence
		 * more of a pain. */
		if (ifr.cmd == SET_VLAN_FLAG_CMD) { /* set_flag */
			ifr.u.flag = xatoul_range(p, 0, 1);
			/* DM: in order to set reorder header, qos must be set */
			ifr.vlan_qos = xatoul_range(argv[3], 0, 7);
		} else if (ifr.cmd == ADD_VLAN_CMD) { /* add */
			ifr.u.VID = xatoul_range(p, 0, VLAN_GROUP_ARRAY_LEN-1);
		} else if (ifr.cmd != DEL_VLAN_CMD) { /* set_{egress|ingress}_map */
			ifr.u.skb_priority = xatou(p);
			ifr.vlan_qos = xatoul_range(argv[3], 0, 7);
		}
	}

	fd = xsocket(AF_INET, SOCK_STREAM, 0);
	if (ioctl(fd, SIOCSIFVLAN, &ifr) < 0) {
		bb_perror_msg_and_die("ioctl error for %s", *argv);
	}

	return 0;
}
Esempio n. 7
0
int usleep_main(int argc UNUSED_PARAM, char **argv)
{
	if (!argv[1]) {
		bb_show_usage();
	}

	usleep(xatou(argv[1]));

	return EXIT_SUCCESS;
}
Esempio n. 8
0
int watch_main(int argc, char **argv)
{
	unsigned opt;
	unsigned period = 2;
	unsigned cmdlen;
	char *header = NULL;
	char *cmd;
	char *tmp;
	char **p;

	opt_complementary = "-1"; // at least one param please
	opt = getopt32(argv, "+dtn:", &tmp);
	//if (opt & 0x1) // -d (ignore)
	//if (opt & 0x2) // -t
	if (opt & 0x4) period = xatou(tmp);
	argv += optind;

	p = argv;
	cmdlen = 1; // 1 for terminal NUL
	while (*p)
		cmdlen += strlen(*p++) + 1;
	tmp = cmd = xmalloc(cmdlen);
	while (*argv) {
		tmp += sprintf(tmp, " %s", *argv);
		argv++;
	}
	cmd++; // skip initial space

	while (1) {
		printf("\033[H\033[J");
		if (!(opt & 0x2)) { // no -t
			int width, len;
			char *thyme;
			time_t t;

			get_terminal_width_height(STDIN_FILENO, &width, 0);
			header = xrealloc(header, width--);
			// '%-*s' pads header with spaces to the full width
			snprintf(header, width, "Every %ds: %-*s", period, width, cmd);
			time(&t);
			thyme = ctime(&t);
			len = strlen(thyme);
			if (len < width)
				strcpy(header + width - len, thyme);
			puts(header);
		}
		fflush(stdout);
		// TODO: 'real' watch pipes cmd's output to itself
		// and does not allow it to overflow the screen
		// (taking into account linewrap!)
		system(cmd);
		sleep(period);
	}
	return 0; // gcc thinks we can reach this :)
}
Esempio n. 9
0
File: xatonum.c Progetto: rplnt/abrt
int xatoi(const char *numstr)
{
    unsigned r;

    if (*numstr != '-')
        return xatoi_positive(numstr);

    r = xatou(numstr + 1);
    if (r > (unsigned)INT_MAX + 1)
        error_msg_and_die("invalid number '%s'", numstr);
    return - (int)r;
}
Esempio n. 10
0
int usleep_main(int argc UNUSED_PARAM, char **argv)
{
	if (!argv[1]) {
		bb_show_usage();
	}

	if (usleep(xatou(argv[1]))) {
		bb_perror_nomsg_and_die();
	}

	return EXIT_SUCCESS;
}
Esempio n. 11
0
static void set_speed_or_die(enum speed_setting type, const char * const arg,
					struct termios * const mode)
{
	speed_t baud;

	baud = tty_value_to_baud(xatou(arg));

	if (type != output_speed) {     /* either input or both */
		cfsetispeed(mode, baud);
	}
	if (type != input_speed) {      /* either output or both */
		cfsetospeed(mode, baud);
	}
}
Esempio n. 12
0
/*

    Parse basic CIDR block  - [!]a.b.c.d/bits

*/
static void parseCIDR( THDX_STRUCT * thdx, char * s )
{
#ifdef SUP_IP6
    sfip_pton(s, &thdx->ip_address);
#else
   char        **args;
   int          nargs;

   if (*s == '!')
   {
       thdx->not_flag = 1;
       s++;
       while( (*s <= ' ') && (*s > 0) ) s++; /* skip whitespace */
   }

   args = mSplit( s , "/", 2, &nargs, 0 );  /* get rule option pairs */

   if( !nargs || nargs > 2  )
   {
       FatalError("%s(%d) => Suppress-Parse: argument pairing error\n", file_name, file_line);
   }

   /*
   *   Keep IP in network order
   */
   thdx->ip_address = inet_addr( args[0] );   

   if( nargs == 2 )
   {
       int i;
       int nbits;
       int mask;

       nbits = xatou( args[1],"suppress: cidr mask bits" );
       mask  = 1 << 31;

       for( i=0; i<nbits; i++ )
       {
          thdx->ip_mask |= mask;
          mask >>= 1;
       }

       /* 
          Put mask in network order 
       */
       thdx->ip_mask = htonl(thdx->ip_mask);       
   }
Esempio n. 13
0
int usleep_main(int argc UNUSED_PARAM, char **argv)
{
	if (!argv[1]) {
		bb_show_usage();
	}

	/* Safe wrt NOFORK? (noforks are not allowed to run for
	 * a long time). Try "usleep 99999999" + ^C + "echo $?"
	 * in hush with FEATURE_SH_NOFORK=y.
	 * At least on uclibc, usleep() thanslates to nanosleep()
	 * which returns early on any signal (even caught one),
	 * and uclibc does not loop back on EINTR.
	 */
	usleep(xatou(argv[1]));

	return EXIT_SUCCESS;
}
Esempio n. 14
0
int sleep_main(int argc UNUSED_PARAM, char **argv)
{
	duration_t duration;

	++argv;
	if (!*argv)
		bb_show_usage();

#if ENABLE_FEATURE_FANCY_SLEEP
# if ENABLE_FLOAT_DURATION
	/* undo busybox.c setlocale */
	setlocale(LC_NUMERIC, "C");
# endif
	duration = 0;
	do {
		duration += parse_duration_str(*argv);
	} while (*++argv);
	sleep_for_duration(duration);
#else /* simple */
	duration = xatou(*argv);
	sleep(duration);
#endif
	return EXIT_SUCCESS;
}
Esempio n. 15
0
int stty_main(int argc UNUSED_PARAM, char **argv)
{
	struct termios mode;
	void (*output_func)(const struct termios *, int);
	const char *file_name = NULL;
	int display_all = 0;
	int stty_state;
	int k;

	INIT_G();

	stty_state = STTY_noargs;
	output_func = do_display;

	/* First pass: only parse/verify command line params */
	k = 0;
	while (argv[++k]) {
		const struct mode_info *mp;
		const struct control_info *cp;
		const char *arg = argv[k];
		const char *argnext = argv[k+1];
		int param;

		if (arg[0] == '-') {
			int i;
			mp = find_mode(arg+1);
			if (mp) {
				if (!(mp->flags & REV))
					goto invalid_argument;
				stty_state &= ~STTY_noargs;
				continue;
			}
			/* It is an option - parse it */
			i = 0;
			while (arg[++i]) {
				switch (arg[i]) {
				case 'a':
					stty_state |= STTY_verbose_output;
					output_func = do_display;
					display_all = 1;
					break;
				case 'g':
					stty_state |= STTY_recoverable_output;
					output_func = display_recoverable;
					break;
				case 'F':
					if (file_name)
						bb_error_msg_and_die("only one device may be specified");
					file_name = &arg[i+1]; /* "-Fdevice" ? */
					if (!file_name[0]) { /* nope, "-F device" */
						int p = k+1; /* argv[p] is argnext */
						file_name = argnext;
						if (!file_name)
							bb_error_msg_and_die(bb_msg_requires_arg, "-F");
						/* remove -F param from arg[vc] */
						while (argv[p]) {
							argv[p] = argv[p+1];
							++p;
						}
					}
					goto end_option;
				default:
					goto invalid_argument;
				}
			}
 end_option:
			continue;
		}

		mp = find_mode(arg);
		if (mp) {
			stty_state &= ~STTY_noargs;
			continue;
		}

		cp = find_control(arg);
		if (cp) {
			if (!argnext)
				bb_error_msg_and_die(bb_msg_requires_arg, arg);
			/* called for the side effect of xfunc death only */
			set_control_char_or_die(cp, argnext, &mode);
			stty_state &= ~STTY_noargs;
			++k;
			continue;
		}

		param = find_param(arg);
		if (param & param_need_arg) {
			if (!argnext)
				bb_error_msg_and_die(bb_msg_requires_arg, arg);
			++k;
		}

		switch (param) {
#ifdef __linux__
		case param_line:
# ifndef TIOCGWINSZ
			xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes);
			break;
# endif /* else fall-through */
#endif
#ifdef TIOCGWINSZ
		case param_rows:
		case param_cols:
		case param_columns:
			xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes);
			break;
		case param_size:
#endif
		case param_speed:
			break;
		case param_ispeed:
			/* called for the side effect of xfunc death only */
			set_speed_or_die(input_speed, argnext, &mode);
			break;
		case param_ospeed:
			/* called for the side effect of xfunc death only */
			set_speed_or_die(output_speed, argnext, &mode);
			break;
		default:
			if (recover_mode(arg, &mode) == 1) break;
			if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) break;
 invalid_argument:
			bb_error_msg_and_die("invalid argument '%s'", arg);
		}
		stty_state &= ~STTY_noargs;
	}

	/* Specifying both -a and -g is an error */
	if ((stty_state & (STTY_verbose_output | STTY_recoverable_output)) ==
		(STTY_verbose_output | STTY_recoverable_output)
	) {
		bb_error_msg_and_die("-a and -g are mutually exclusive");
	}
	/* Specifying -a or -g with non-options is an error */
	if ((stty_state & (STTY_verbose_output | STTY_recoverable_output))
	 && !(stty_state & STTY_noargs)
	) {
		bb_error_msg_and_die("modes may not be set when -a or -g is used");
	}

	/* Now it is safe to start doing things */
	if (file_name) {
		G.device_name = file_name;
		xmove_fd(xopen_nonblocking(G.device_name), STDIN_FILENO);
		ndelay_off(STDIN_FILENO);
	}

	/* Initialize to all zeroes so there is no risk memcmp will report a
	   spurious difference in an uninitialized portion of the structure */
	memset(&mode, 0, sizeof(mode));
	if (tcgetattr(STDIN_FILENO, &mode))
		perror_on_device_and_die("%s");

	if (stty_state & (STTY_verbose_output | STTY_recoverable_output | STTY_noargs)) {
		G.max_col = get_terminal_width(STDOUT_FILENO);
		output_func(&mode, display_all);
		return EXIT_SUCCESS;
	}

	/* Second pass: perform actions */
	k = 0;
	while (argv[++k]) {
		const struct mode_info *mp;
		const struct control_info *cp;
		const char *arg = argv[k];
		const char *argnext = argv[k+1];
		int param;

		if (arg[0] == '-') {
			mp = find_mode(arg+1);
			if (mp) {
				set_mode(mp, 1 /* reversed */, &mode);
				stty_state |= STTY_require_set_attr;
			}
			/* It is an option - already parsed. Skip it */
			continue;
		}

		mp = find_mode(arg);
		if (mp) {
			set_mode(mp, 0 /* non-reversed */, &mode);
			stty_state |= STTY_require_set_attr;
			continue;
		}

		cp = find_control(arg);
		if (cp) {
			++k;
			set_control_char_or_die(cp, argnext, &mode);
			stty_state |= STTY_require_set_attr;
			continue;
		}

		param = find_param(arg);
		if (param & param_need_arg) {
			++k;
		}

		switch (param) {
#ifdef __linux__
		case param_line:
			mode.c_line = xatoul_sfx(argnext, stty_suffixes);
			stty_state |= STTY_require_set_attr;
			break;
#endif
#ifdef TIOCGWINSZ
		case param_cols:
		case param_columns:
			set_window_size(-1, xatoul_sfx(argnext, stty_suffixes));
			break;
		case param_size:
			display_window_size(0);
			break;
		case param_rows:
			set_window_size(xatoul_sfx(argnext, stty_suffixes), -1);
			break;
#endif
		case param_speed:
			display_speed(&mode, 0);
			break;
		case param_ispeed:
			set_speed_or_die(input_speed, argnext, &mode);
			stty_state |= (STTY_require_set_attr | STTY_speed_was_set);
			break;
		case param_ospeed:
			set_speed_or_die(output_speed, argnext, &mode);
			stty_state |= (STTY_require_set_attr | STTY_speed_was_set);
			break;
		default:
			if (recover_mode(arg, &mode) == 1)
				stty_state |= STTY_require_set_attr;
			else /* true: if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) */{
				set_speed_or_die(both_speeds, arg, &mode);
				stty_state |= (STTY_require_set_attr | STTY_speed_was_set);
			} /* else - impossible (caught in the first pass):
				bb_error_msg_and_die("invalid argument '%s'", arg); */
		}
	}

	if (stty_state & STTY_require_set_attr) {
		struct termios new_mode;

		if (tcsetattr(STDIN_FILENO, TCSADRAIN, &mode))
			perror_on_device_and_die("%s");

		/* POSIX (according to Zlotnick's book) tcsetattr returns zero if
		   it performs *any* of the requested operations.  This means it
		   can report 'success' when it has actually failed to perform
		   some proper subset of the requested operations.  To detect
		   this partial failure, get the current terminal attributes and
		   compare them to the requested ones */

		/* Initialize to all zeroes so there is no risk memcmp will report a
		   spurious difference in an uninitialized portion of the structure */
		memset(&new_mode, 0, sizeof(new_mode));
		if (tcgetattr(STDIN_FILENO, &new_mode))
			perror_on_device_and_die("%s");

		if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) {
/*
 * I think the below chunk is not necessary on Linux.
 * If you are deleting it, also delete STTY_speed_was_set bit -
 * it is only ever checked here.
 */
#if 0 /* was "if CIBAUD" */
			/* SunOS 4.1.3 (at least) has the problem that after this sequence,
			   tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
			   sometimes (m1 != m2).  The only difference is in the four bits
			   of the c_cflag field corresponding to the baud rate.  To save
			   Sun users a little confusion, don't report an error if this
			   happens.  But suppress the error only if we haven't tried to
			   set the baud rate explicitly -- otherwise we'd never give an
			   error for a true failure to set the baud rate */

			new_mode.c_cflag &= (~CIBAUD);
			if ((stty_state & STTY_speed_was_set)
			 || memcmp(&mode, &new_mode, sizeof(mode)) != 0)
#endif
				perror_on_device_and_die("%s: cannot perform all requested operations");
		}
	}

	return EXIT_SUCCESS;
}
Esempio n. 16
0
int sleep_main(int argc UNUSED_PARAM, char **argv)
{
#if ENABLE_FEATURE_FLOAT_SLEEP
	double duration;
	struct timespec ts;
#else
	unsigned duration;
#endif

	++argv;
	if (!*argv)
		bb_show_usage();

#if ENABLE_FEATURE_FLOAT_SLEEP

	duration = 0;
	do {
		char *arg = *argv;
		if (strchr(arg, '.')) {
			double d;
			char *pp;
			int len = strspn(arg, "0123456789.");
			char sv = arg[len];
			arg[len] = '\0';
			errno = 0;
			d = strtod(arg, &pp);
			if (errno || *pp)
				bb_show_usage();
			arg[len] = sv;
			len--;
			sv = arg[len];
			arg[len] = '1';
			duration += d * xatoul_sfx(&arg[len], sfx);
			arg[len] = sv;
		} else
			duration += xatoul_sfx(arg, sfx);
	} while (*++argv);

	ts.tv_sec = MAXINT(typeof(ts.tv_sec));
	ts.tv_nsec = 0;
	if (duration >= 0 && duration < ts.tv_sec) {
		ts.tv_sec = duration;
		ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
	}
	do {
		errno = 0;
		nanosleep(&ts, &ts);
	} while (errno == EINTR);

#elif ENABLE_FEATURE_FANCY_SLEEP

	duration = 0;
	do {
		duration += xatou_range_sfx(*argv, 0, UINT_MAX - duration, sfx);
	} while (*++argv);
	sleep(duration);

#else /* simple */

	duration = xatou(*argv);
	sleep(duration);
	// Off. If it's really needed, provide example why
	//if (sleep(duration)) {
	//	bb_perror_nomsg_and_die();
	//}

#endif

	return EXIT_SUCCESS;
}
Esempio n. 17
0
int rtcwake_main(int argc UNUSED_PARAM, char **argv)
{
	unsigned opt;
	const char *rtcname = NULL;
	const char *suspend = "standby";
	const char *opt_seconds;
	const char *opt_time;

	time_t rtc_time;
	time_t sys_time;
	time_t alarm_time = alarm_time;
	unsigned seconds = seconds; /* for compiler */
	int utc = -1;
	int fd;

#if ENABLE_LONG_OPTS
	static const char rtcwake_longopts[] ALIGN1 =
		"auto\0"    No_argument "a"
		"local\0"   No_argument "l"
		"utc\0"     No_argument "u"
		"device\0"  Required_argument "d"
		"mode\0"    Required_argument "m"
		"seconds\0" Required_argument "s"
		"time\0"    Required_argument "t"
		;
#endif
	opt = getopt32long(argv,
			/* Must have -s or -t, exclusive */
			"^alud:m:s:t:" "\0" "s:t:s--t:t--s", rtcwake_longopts,
			&rtcname, &suspend, &opt_seconds, &opt_time);

	/* this is the default
	if (opt & RTCWAKE_OPT_AUTO)
		utc = -1;
	*/
	if (opt & (RTCWAKE_OPT_UTC | RTCWAKE_OPT_LOCAL))
		utc = opt & RTCWAKE_OPT_UTC;
	if (opt & RTCWAKE_OPT_SECONDS) {
		/* alarm time, seconds-to-sleep (relative) */
		seconds = xatou(opt_seconds);
	} else {
		/* RTCWAKE_OPT_TIME */
		/* alarm time, time_t (absolute, seconds since 1/1 1970 UTC) */
		if (sizeof(alarm_time) <= sizeof(long))
			alarm_time = xatol(opt_time);
		else
			alarm_time = xatoll(opt_time);
	}

	if (utc == -1)
		utc = rtc_adjtime_is_utc();

	/* the rtcname is relative to /dev */
	xchdir("/dev");

	/* this RTC must exist and (if we'll sleep) be wakeup-enabled */
	fd = rtc_xopen(&rtcname, O_RDONLY);

	if (strcmp(suspend, "on") != 0)
		if (!may_wakeup(rtcname))
			bb_error_msg_and_die("%s not enabled for wakeup events", rtcname);

	/* relative or absolute alarm time, normalized to time_t */
	sys_time = time(NULL);
	{
		struct tm tm_time;
		rtc_read_tm(&tm_time, fd);
		rtc_time = rtc_tm2time(&tm_time, utc);
	}

	if (opt & RTCWAKE_OPT_TIME) {
		/* Correct for RTC<->system clock difference */
		alarm_time += rtc_time - sys_time;
		if (alarm_time < rtc_time)
			/*
			 * Compat message text.
			 * I'd say "RTC time is already ahead of ..." instead.
			 */
			bb_error_msg_and_die("time doesn't go backward to %s", ctime(&alarm_time));
	} else
		alarm_time = rtc_time + seconds + 1;

	setup_alarm(fd, &alarm_time, rtc_time);
	sync();
#if 0 /*debug*/
	printf("sys_time: %s", ctime(&sys_time));
	printf("rtc_time: %s", ctime(&rtc_time));
#endif
	printf("wakeup from \"%s\" at %s", suspend, ctime(&alarm_time));
	fflush_all();
	usleep(10 * 1000);

	if (strcmp(suspend, "on") != 0)
		xopen_xwrite_close(SYS_POWER_PATH, suspend);
	else {
		/* "fake" suspend ... we'll do the delay ourselves */
		unsigned long data;

		do {
			ssize_t ret = safe_read(fd, &data, sizeof(data));
			if (ret < 0) {
				bb_perror_msg("rtc read");
				break;
			}
		} while (!(data & RTC_AF));
	}

	xioctl(fd, RTC_AIE_OFF, 0);

	if (ENABLE_FEATURE_CLEAN_UP)
		close(fd);

	return EXIT_SUCCESS;
}
Esempio n. 18
0
int main(int argc, char **argv)
{
    abrt_init(argv);

    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    const char *program_usage_string = _(
        "\n& [-vf] [-c CONFFILE]... [-F FMTFILE] [-A FMTFILE2] -d DIR"
        "\nor:"
        "\n& [-v] [-c CONFFILE]... [-d DIR] -t[ID] FILE..."
        "\nor:"
        "\n& [-v] [-c CONFFILE]... [-d DIR] -t[ID] -w"
        "\nor:"
        "\n& [-v] [-c CONFFILE]... -h DUPHASH"
        "\n"
        "\nReports problem to MantisBT."
        "\n"
        "\nThe tool reads DIR. Then it tries to find an issue"
        "\nwith the same abrt_hash in custom field 'abrt_hash'."
        "\n"
        "\nIf such issue is not found, then a new issue is created. Elements of DIR"
        "\nare stored in the issue as part of issue description or as attachments,"
        "\ndepending on their type and size."
        "\n"
        "\nOtherwise, if such issue is found and it is marked as CLOSED DUPLICATE,"
        "\nthe tool follows the chain of duplicates until it finds a non-DUPLICATE issue."
        "\nThe tool adds a new comment to found issue."
        "\n"
        "\nThe URL to new or modified issue is printed to stdout and recorded in"
        "\n'reported_to' element."
        "\n"
        "\nOption -t uploads FILEs to the already created issue on MantisBT site."
        "\nThe issue ID is retrieved from directory specified by -d DIR."
        "\nIf problem data in DIR was never reported to MantisBT, upload will fail."
        "\n"
        "\nOption -tID uploads FILEs to the issue with specified ID on MantisBT site."
        "\n-d DIR is ignored."
        "\n"
        "\nOption -r sets the last url from reporter_to element which is prefixed with"
        "\nTRACKER_NAME to URL field. This option is applied only when a new issue is to be"
        "\nfiled. The default value is 'ABRT Server'"
        "\n"
        "\nIf not specified, CONFFILE defaults to "CONF_DIR"/plugins/mantisbt.conf"
        "\nand user's local ~"USER_HOME_CONFIG_PATH"/mantisbt.conf."
        "\nIts lines should have 'PARAM = VALUE' format."
        "\nRecognized string parameters: MantisbtURL, Login, Password, Project, ProjectVersion."
        "\nRecognized boolean parameter (VALUE should be 1/0, yes/no): SSLVerify, CreatePrivate."
        "\nUser's local configuration overrides the system wide configuration."
        "\nParameters can be overridden via $Mantisbt_PARAM environment variables."
        "\n"
        "\nFMTFILE default to "CONF_DIR"/plugins/mantisbt_format.conf."
        "\nFMTFILE2 default to "CONF_DIR"/plugins/mantisbt_formatdup.conf."
    );

    enum {
        OPT_v = 1 << 0,
        OPT_d = 1 << 1,
        OPT_c = 1 << 2,
        OPT_F = 1 << 3,
        OPT_A = 1 << 4,
        OPT_t = 1 << 5,
        OPT_f = 1 << 6,
        OPT_h = 1 << 7,
        OPT_r = 1 << 8,
        OPT_D = 1 << 9,
    };

    const char *dump_dir_name = ".";
    GList *conf_file = NULL;
    const char *fmt_file = CONF_DIR"/plugins/mantisbt_format.conf";
    const char *fmt_file2 = CONF_DIR"/plugins/mantisbt_formatdup.conf";
    char *abrt_hash = NULL;
    char *ticket_no = NULL;
    const char *tracker_str = "ABRT Server";
    char *debug_str = NULL;
    mantisbt_settings_t mbt_settings = { 0 };
    /* Keep enum above and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_STRING(   'd', NULL, &dump_dir_name , "DIR"    , _("Problem directory")),
        OPT_LIST(     'c', NULL, &conf_file     , "FILE"   , _("Configuration file (may be given many times)")),
        OPT_STRING(   'F', NULL, &fmt_file      , "FILE"   , _("Formatting file for initial comment")),
        OPT_STRING(   'A', NULL, &fmt_file2     , "FILE"   , _("Formatting file for duplicates")),
        OPT_OPTSTRING('t', "ticket", &ticket_no , "ID"     , _("Attach FILEs [to issue with this ID]")),
        OPT_BOOL(     'f', NULL, NULL,                       _("Force reporting even if this problem is already reported")),
        OPT_STRING(   'h', "duphash", &abrt_hash, "DUPHASH", _("Print BUG_ID which has given DUPHASH")),
        OPT_STRING(   'r', "tracker", &tracker_str, "TRACKER_NAME", _("A name of bug tracker for an additional URL from 'reported_to'")),

        OPT_OPTSTRING('D', "debug", &debug_str  , "STR"    , _("Debug")),
        OPT_END()
    };

    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
    argv += optind;

    export_abrt_envvars(0);

    map_string_t *settings = new_map_string();

    {
        char *local_conf = NULL;
        if (!conf_file)
        {
            conf_file = g_list_append(conf_file, (char*) CONF_DIR"/plugins/mantisbt.conf");
            local_conf = xasprintf("%s"USER_HOME_CONFIG_PATH"/mantisbt.conf", getenv("HOME"));
            conf_file = g_list_append(conf_file, local_conf);
        }
        while (conf_file)
        {
            char *fn = (char *)conf_file->data;
            log_notice("Loading settings from '%s'", fn);
            load_conf_file(fn, settings, /*skip key w/o values:*/ false);
            log_debug("Loaded '%s'", fn);
            conf_file = g_list_delete_link(conf_file, conf_file);
        }
        free(local_conf);

        struct dump_dir *dd = NULL;
        if (abrt_hash == NULL)
        {
            dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
            if (!dd)
                error_msg_and_die(_("Can't open problem dir '%s'."), dump_dir_name);
        }

        set_settings(&mbt_settings, settings, dd);
        dd_close(dd);
        /* WRONG! set_settings() does not copy the strings, it merely sets up pointers
         * to settings[] dictionary:
         */
        /*free_map_string(settings);*/
    }

    /* No connection is opened between client and server. Users authentication
     * is performed on every SOAP method call. In the first step we verify the
     * credentials by calling 'mc_login' method.  In the case the credentials are
     * correctly applies the reporter uses them in the next requests. It is not
     * necessary to call 'mc_login' method because the method provides only
     * verification of credentials.
     */
    verify_credentials(&mbt_settings);

    if (abrt_hash)
    {
        log_warning(_("Looking for similar problems in MantisBT"));
        GList *ids = mantisbt_search_by_abrt_hash(&mbt_settings, abrt_hash);
        mantisbt_settings_free(&mbt_settings);

        if (ids == NULL)
            return EXIT_FAILURE;

        puts(ids->data);
        response_values_free(ids);
        return EXIT_SUCCESS;
    }

    mantisbt_get_project_id_from_name(&mbt_settings);

    if (opts & OPT_t)
    {
        if (!argv[0])
            show_usage_and_die(program_usage_string, program_options);

        if (!ticket_no)
        {
            struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
            if (!dd)
                xfunc_die();
            report_result_t *reported_to = find_in_reported_to(dd, "MantisBT");
            dd_close(dd);

            if (!reported_to || !reported_to->url)
                error_msg_and_die(_("Can't get MantisBT ID because this problem has not yet been reported to MantisBT."));

            char *url = reported_to->url;
            reported_to->url = NULL;
            free_report_result(reported_to);

            if (prefixcmp(url, mbt_settings.m_mantisbt_url) != 0)
                error_msg_and_die(_("This problem has been reported to MantisBT '%s' which differs from the configured MantisBT '%s'."), url, mbt_settings.m_mantisbt_url);

            ticket_no = strrchr(url, '=');
            if (!ticket_no)
                error_msg_and_die(_("Malformed url to MantisBT '%s'."), url);

            /* won't ever call free on it - it simplifies the code a lot */
            ticket_no = xstrdup(ticket_no + 1);
            log_warning(_("Using MantisBT ID '%s'"), ticket_no);
        }

        /* Attach files to existing MantisBT issues */
        while (*argv)
        {
            const char *path = *argv++;
            char *filename = basename(path);
            log_warning(_("Attaching file '%s' to issue %s"), filename, ticket_no);
            mantisbt_attach_file(&mbt_settings, ticket_no, filename, path);
        }

        return 0;
    }

    /* Create new issue in MantisBT */

    if (!(opts & OPT_f))
    {
        struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
        if (!dd)
            xfunc_die();
        report_result_t *reported_to = find_in_reported_to(dd, "MantisBT");
        dd_close(dd);

        if (reported_to && reported_to->url)
        {
            char *msg = xasprintf(_("This problem was already reported to MantisBT (see '%s')."
                            " Do you still want to create a new issue?"),
                            reported_to->url);
            int yes = ask_yes_no(msg);
            free(msg);
            if (!yes)
                return 0;
        }
        free_report_result(reported_to);
    }

    problem_data_t *problem_data = create_problem_data_for_reporting(dump_dir_name);
    if (!problem_data)
        xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */

    const char *category = problem_data_get_content_or_die(problem_data, FILENAME_COMPONENT);
    const char *duphash   = problem_data_get_content_or_die(problem_data, FILENAME_DUPHASH);

    if (opts & OPT_D)
    {
        problem_formatter_t *pf = problem_formatter_new();
        problem_formatter_add_section(pf, PR_SEC_ADDITIONAL_INFO, /* optional section */ 0);

        if (problem_formatter_load_file(pf, fmt_file))
            error_msg_and_die("Invalid format file: %s", fmt_file);

        problem_report_t *pr = NULL;
        if (problem_formatter_generate_report(pf, problem_data, &pr))
            error_msg_and_die("Failed to format issue report from problem data");

        printf("summary: %s\n"
                "\n"
                "Description:\n%s\n"
                "Additional info:\n%s\n"
                , problem_report_get_summary(pr)
                , problem_report_get_description(pr)
                , problem_report_get_section(pr, PR_SEC_ADDITIONAL_INFO)
        );

        puts("attachments:");
        for (GList *a = problem_report_get_attachments(pr); a != NULL; a = g_list_next(a))
            printf(" %s\n", (const char *)a->data);

        problem_report_free(pr);
        problem_formatter_free(pf);
        exit(0);
    }

     unsigned long bug_id = 0;

    /* If REMOTE_RESULT contains "DUPLICATE 12345", we consider it a dup of 12345
     * and won't search on MantisBT server.
     */
    char *remote_result;
    remote_result = problem_data_get_content_or_NULL(problem_data, FILENAME_REMOTE_RESULT);
    if (remote_result)
    {
        char *cmd = strtok(remote_result, " \n");
        char *id = strtok(NULL, " \n");

        if (!prefixcmp(cmd, "DUPLICATE"))
        {
            errno = 0;
            char *e;
            bug_id = strtoul(id, &e, 10);
            if (errno || id == e || *e != '\0' || bug_id > INT_MAX)
            {
                /* error / no digits / illegal trailing chars / too big a number */
                bug_id = 0;
            }
        }
    }

    mantisbt_issue_info_t *ii;
    if (!bug_id)
    {
        log_warning(_("Checking for duplicates"));

        int existing_id = -1;
        int crossver_id = -1;
        {
            /* Figure out whether we want to match category
             * when doing dup search.
             */
            const char *category_substitute = is_in_comma_separated_list(category, mbt_settings.m_DontMatchComponents) ? NULL : category;

            /* We don't do dup detection across versions (see below why),
             * but we do add a note if cross-version potential dup exists.
             * For that, we search for cross version dups first:
             */
            // SOAP API searching method is not in the final version, it's possible the project will be string
            GList *crossver_bugs_ids = mantisbt_search_duplicate_issues(&mbt_settings, category_substitute, /*version*/ NULL, duphash);

            unsigned crossver_bugs_count = g_list_length(crossver_bugs_ids);
            log_debug("MantisBT has %i reports with duphash '%s' including cross-version ones",
                    crossver_bugs_count, duphash);
            if (crossver_bugs_count > 0)
                crossver_id = atoi(g_list_first(crossver_bugs_ids)->data);

            if (crossver_bugs_count > 0)
            {
                // SOAP API searching method is not in the final version, it's possible the project will be string
                GList *dup_bugs_ids = mantisbt_search_duplicate_issues(&mbt_settings, category_substitute, mbt_settings.m_project_version, duphash);

                unsigned dup_bugs_count =  g_list_length(dup_bugs_ids);
                log_debug("MantisBT has %i reports with duphash '%s'",
                        dup_bugs_count, duphash);
                if (dup_bugs_count > 0)
                    existing_id = atoi(g_list_first(dup_bugs_ids)->data);
            }
        }

        if (existing_id < 0)
        {
            /* Create new issue */
            log_warning(_("Creating a new issue"));
            problem_formatter_t *pf = problem_formatter_new();
            problem_formatter_add_section(pf, PR_SEC_ADDITIONAL_INFO, 0);

            if (problem_formatter_load_file(pf, fmt_file))
                error_msg_and_die(_("Invalid format file: %s"), fmt_file);

            problem_report_t *pr = NULL;
            if (problem_formatter_generate_report(pf, problem_data, &pr))
                error_msg_and_die(_("Failed to format problem data"));

            if (crossver_id >= 0)
                problem_report_buffer_printf(
                        problem_report_get_buffer(pr, PR_SEC_DESCRIPTION),
                        "\nPotential duplicate: issue %u\n", crossver_id);

            problem_formatter_free(pf);

            /* get tracker URL if exists */
            struct dump_dir *dd = dd_opendir(dump_dir_name, 0);
            char *tracker_url = NULL;
            if (dd)
            {
                report_result_t *reported_to = find_in_reported_to(dd, tracker_str);
                dd_close(dd);

                if (reported_to && reported_to->url)
                {
                    log_warning(_("Adding External URL to issue"));
                    tracker_url = xstrdup(reported_to->url);
                    free_report_result(reported_to);
                }
            }

            int new_id = mantisbt_create_new_issue(&mbt_settings, problem_data, pr, tracker_url);

            free(tracker_url);

            if (new_id == -1)
                return EXIT_FAILURE;

            log_warning(_("Adding attachments to issue %i"), new_id);
            char *new_id_str = xasprintf("%u", new_id);

            for (GList *a = problem_report_get_attachments(pr); a != NULL; a = g_list_next(a))
            {
                const char *item_name = (const char *)a->data;
                struct problem_item *item = problem_data_get_item_or_NULL(problem_data, item_name);
                if (!item)
                    continue;
                else if (item->flags & CD_FLAG_TXT)
                    mantisbt_attach_data(&mbt_settings, new_id_str, item_name, item->content, strlen(item->content));
                else if (item->flags & CD_FLAG_BIN)
                    mantisbt_attach_file(&mbt_settings, new_id_str, item_name, item->content);
            }

            free(new_id_str);
            problem_report_free(pr);
            ii = mantisbt_issue_info_new();
            ii->mii_id = new_id;
            ii->mii_status = xstrdup("new");

            goto finish;
        }

        bug_id = existing_id;
    }

    ii = mantisbt_get_issue_info(&mbt_settings, bug_id);

    log_warning(_("Bug is already reported: %i"), ii->mii_id);

    /* Follow duplicates */
    if ((strcmp(ii->mii_status, "closed") == 0)
     && (strcmp(ii->mii_resolution, "duplicate") == 0)
    ) {
        mantisbt_issue_info_t *origin = mantisbt_find_origin_bug_closed_duplicate(&mbt_settings, ii);
        if (origin)
        {
            mantisbt_issue_info_free(ii);
            ii = origin;
        }
    }

    /* TODO CC list
     * Is no MantisBT SOAP API method which allows adding users to CC list
     * without updating issue.
     */

    /* Add comment and bt */
    const char *comment = problem_data_get_content_or_NULL(problem_data, FILENAME_COMMENT);
    if (comment && comment[0])
    {
        problem_formatter_t *pf = problem_formatter_new();

        if (problem_formatter_load_file(pf, fmt_file2))
            error_msg_and_die(_("Invalid duplicate format file: '%s"), fmt_file2);

        problem_report_t *pr;
        if (problem_formatter_generate_report(pf, problem_data, &pr))
            error_msg_and_die(_("Failed to format duplicate comment from problem data"));

        const char *mbtcomment = problem_report_get_description(pr);

        int dup_comment = is_comment_dup(ii->mii_notes, mbtcomment);
        if (!dup_comment)
        {
            log_warning(_("Adding new comment to issue %d"), ii->mii_id);
            mantisbt_add_issue_note(&mbt_settings, ii->mii_id, mbtcomment);

            const char *bt = problem_data_get_content_or_NULL(problem_data, FILENAME_BACKTRACE);
            unsigned rating = 0;
            const char *rating_str = problem_data_get_content_or_NULL(problem_data, FILENAME_RATING);
            /* python doesn't have rating file */
            if (rating_str)
                rating = xatou(rating_str);
            if (bt && rating > ii->mii_best_bt_rating)
            {
                char *bug_id_str = xasprintf("%i", ii->mii_id);

                log_warning(_("Attaching better backtrace"));

                // find unique filename of attachment
                char *name = NULL;
                for (int i = 0;; ++i)
                {
                    if (i == 0)
                        name = xasprintf("%s", FILENAME_BACKTRACE);
                    else
                        name = xasprintf("%s%d", FILENAME_BACKTRACE, i);

                    if (g_list_find_custom(ii->mii_attachments, name, (GCompareFunc) strcmp) == NULL)
                        break;

                    free(name);
                }
                mantisbt_attach_data(&mbt_settings, bug_id_str, name, bt, strlen(bt));

                free(name);
                free(bug_id_str);
            }
        }
        else
            log_warning(_("Found the same comment in the issue history, not adding a new one"));

        problem_report_free(pr);
        problem_formatter_free(pf);
    }

finish:
    log_warning(_("Status: %s%s%s %s/view.php?id=%u"),
                ii->mii_status,
                ii->mii_resolution ? " " : "",
                ii->mii_resolution ? ii->mii_resolution : "",
                mbt_settings.m_mantisbt_url,
                ii->mii_id);

    struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (dd)
    {
        report_result_t rr = { .label = (char *)"MantisBT" };
        rr.url = xasprintf("%s/view.php?id=%u", mbt_settings.m_mantisbt_url, ii->mii_id);
        add_reported_to_entry(dd, &rr);
        free(rr.url);
        dd_close(dd);
    }

    mantisbt_settings_free(&mbt_settings);
    return 0;
}
Esempio n. 19
0
int main(int argc, char **argv)
{
    abrt_init(argv);

    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    /* Can't keep these strings/structs static: _() doesn't support that */
    const char *program_usage_string = _(
        "\n& [-vbf] [-g GROUP-NAME]... [-c CONFFILE]... [-F FMTFILE] [-A FMTFILE2] -d DIR"
        "\nor:"
        "\n& [-v] [-c CONFFILE]... [-d DIR] -t[ID] FILE..."
        "\nor:"
        "\n& [-v] [-c CONFFILE]... [-d DIR] -t[ID] -w"
        "\nor:"
        "\n& [-v] [-c CONFFILE]... -h DUPHASH"
        "\n"
        "\nReports problem to Bugzilla."
        "\n"
        "\nThe tool reads DIR. Then it logs in to Bugzilla and tries to find a bug"
        "\nwith the same abrt_hash:HEXSTRING in 'Whiteboard'."
        "\n"
        "\nIf such bug is not found, then a new bug is created. Elements of DIR"
        "\nare stored in the bug as part of bug description or as attachments,"
        "\ndepending on their type and size."
        "\n"
        "\nOtherwise, if such bug is found and it is marked as CLOSED DUPLICATE,"
        "\nthe tool follows the chain of duplicates until it finds a non-DUPLICATE bug."
        "\nThe tool adds a new comment to found bug."
        "\n"
        "\nThe URL to new or modified bug is printed to stdout and recorded in"
        "\n'reported_to' element."
        "\n"
        "\nOption -t uploads FILEs to the already created bug on Bugzilla site."
        "\nThe bug ID is retrieved from directory specified by -d DIR."
        "\nIf problem data in DIR was never reported to Bugzilla, upload will fail."
        "\n"
        "\nOption -tID uploads FILEs to the bug with specified ID on Bugzilla site."
        "\n-d DIR is ignored."
        "\n"
        "\nOption -w adds bugzilla user to bug's CC list."
        "\n"
        "\nIf not specified, CONFFILE defaults to "CONF_DIR"/plugins/bugzilla.conf"
        "\nIts lines should have 'PARAM = VALUE' format."
        "\nRecognized string parameters: BugzillaURL, Login, Password, OSRelease."
        "\nRecognized boolean parameter (VALUE should be 1/0, yes/no): SSLVerify."
        "\nParameters can be overridden via $Bugzilla_PARAM environment variables."
        "\n"
        "\nFMTFILE and FMTFILE2 default to "CONF_DIR"/plugins/bugzilla_format.conf"
    );
    enum {
        OPT_v = 1 << 0,
        OPT_d = 1 << 1,
        OPT_c = 1 << 2,
        OPT_F = 1 << 3,
        OPT_A = 1 << 4,
        OPT_t = 1 << 5,
        OPT_b = 1 << 6,
        OPT_f = 1 << 7,
        OPT_w = 1 << 8,
        OPT_h = 1 << 9,
        OPT_g = 1 << 10,
        OPT_D = 1 << 11,
    };
    const char *dump_dir_name = ".";
    GList *conf_file = NULL;
    const char *fmt_file = CONF_DIR"/plugins/bugzilla_format.conf";
    const char *fmt_file2 = fmt_file;
    char *abrt_hash = NULL;
    char *ticket_no = NULL;
    char *debug_str = NULL;
    GList *group = NULL;
    /* Keep enum above and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_STRING(   'd', NULL, &dump_dir_name , "DIR"    , _("Problem directory")),
        OPT_LIST(     'c', NULL, &conf_file     , "FILE"   , _("Configuration file (may be given many times)")),
        OPT_STRING(   'F', NULL, &fmt_file      , "FILE"   , _("Formatting file for initial comment")),
        OPT_STRING(   'A', NULL, &fmt_file2     , "FILE"   , _("Formatting file for duplicates")),
        OPT_OPTSTRING('t', "ticket", &ticket_no , "ID"     , _("Attach FILEs [to bug with this ID]")),
        OPT_BOOL(     'b', NULL, NULL,                       _("When creating bug, attach binary files too")),
        OPT_BOOL(     'f', NULL, NULL,                       _("Force reporting even if this problem is already reported")),
        OPT_BOOL(     'w', NULL, NULL,                       _("Add bugzilla user to CC list [of bug with this ID]")),
        OPT_STRING(   'h', "duphash", &abrt_hash, "DUPHASH", _("Print BUG_ID which has given DUPHASH")),
        OPT_LIST(     'g', "group", &group      , "GROUP"  , _("Restrict access to this group only")),
        OPT_OPTSTRING('D', "debug", &debug_str  , "STR"    , _("Debug")),
        OPT_END()
    };
    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
    argv += optind;

    export_abrt_envvars(0);

    map_string_t *settings = new_map_string();
    struct bugzilla_struct rhbz = { 0 };
    {
        if (!conf_file)
            conf_file = g_list_append(conf_file, (char*) CONF_DIR"/plugins/bugzilla.conf");
        while (conf_file)
        {
            char *fn = (char *)conf_file->data;
            VERB1 log("Loading settings from '%s'", fn);
            load_conf_file(fn, settings, /*skip key w/o values:*/ false);
            VERB3 log("Loaded '%s'", fn);
            conf_file = g_list_delete_link(conf_file, conf_file);
        }
        set_settings(&rhbz, settings);
        /* WRONG! set_settings() does not copy the strings, it merely sets up pointers
         * to settings[] dictionary:
         */
        /*free_map_string(settings);*/
    }

    VERB1 log("Initializing XML-RPC library");
    xmlrpc_env env;
    xmlrpc_env_init(&env);
    xmlrpc_client_setup_global_const(&env);
    if (env.fault_occurred)
        abrt_xmlrpc_die(&env);
    xmlrpc_env_clean(&env);

    struct abrt_xmlrpc *client;
    client = abrt_xmlrpc_new_client(rhbz.b_bugzilla_xmlrpc, rhbz.b_ssl_verify);
    unsigned rhbz_ver = rhbz_version(client);

    if (abrt_hash)
    {
        log(_("Looking for similar problems in bugzilla"));
        char *hash;
        if (prefixcmp(abrt_hash, "abrt_hash:"))
            hash = xasprintf("abrt_hash:%s", abrt_hash);
        else
            hash = xstrdup(abrt_hash);

        /* it's Fedora specific */
        xmlrpc_value *all_bugs = rhbz_search_duphash(client,
                                /*product:*/ "Fedora",
                                /*version:*/ NULL,
                                /*component:*/ NULL,
                                hash);
        free(hash);
        unsigned all_bugs_size = rhbz_array_size(all_bugs);
        if (all_bugs_size > 0)
        {
            int bug_id = rhbz_get_bug_id_from_array0(all_bugs, rhbz_ver);
            printf("%i\n", bug_id);
        }

        return EXIT_SUCCESS;
    }

    if (rhbz.b_login[0] == '\0')
    {
        free(rhbz.b_login);
        rhbz.b_login = ask_bz_login(_("Login is not provided by configuration. Please enter your BZ login:"******"Password is not provided by configuration. Please enter the password for '%s':"), rhbz.b_login);
        rhbz.b_password = ask_bz_password(question);
        free(question);
    }

    if (opts & OPT_t)
    {
        if ((!argv[0] && !(opts & OPT_w)) || (argv[0] && (opts & OPT_w)))
            show_usage_and_die(program_usage_string, program_options);

        if (!ticket_no)
        {
            struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
            if (!dd)
                xfunc_die();
            report_result_t *reported_to = find_in_reported_to(dd, "Bugzilla:");
            dd_close(dd);

            if (!reported_to || !reported_to->url)
                error_msg_and_die(_("Can't get Bugzilla ID because this problem has not yet been reported to Bugzilla."));

            char *url = reported_to->url;
            reported_to->url = NULL;
            free_report_result(reported_to);

            if (prefixcmp(url, rhbz.b_bugzilla_url) != 0)
                error_msg_and_die(_("This problem has been reported to Bugzilla '%s' which differs from the configured Bugzilla '%s'."), url, rhbz.b_bugzilla_url);

            ticket_no = strrchr(url, '=');
            if (!ticket_no)
                error_msg_and_die(_("Malformed url to Bugzilla '%s'."), url);

            /* won't ever call free on it - it simplifies the code a lot */
            ticket_no = xstrdup(ticket_no + 1);
            log(_("Using Bugzilla ID '%s'"), ticket_no);
        }

        login(client, &rhbz);

        if (opts & OPT_w)
            rhbz_mail_to_cc(client, xatoi_positive(ticket_no), rhbz.b_login, /* require mail notify */ 0);
        else
        {   /* Attach files to existing BZ */
            while (*argv)
            {
                const char *filename = *argv++;
                VERB1 log("Attaching file '%s' to bug %s", filename, ticket_no);

                int fd = open(filename, O_RDONLY);
                if (fd < 0)
                {
                    perror_msg("Can't open '%s'", filename);
                    continue;
                }

                struct stat st;
                if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode))
                {
                    error_msg("'%s': not a regular file", filename);
                    close(fd);
                    continue;
                }

                rhbz_attach_fd(client, ticket_no, filename, fd, /*flags*/ 0);
                close(fd);
            }
        }

        log(_("Logging out"));
        rhbz_logout(client);

#if 0  /* enable if you search for leaks (valgrind etc) */
        abrt_xmlrpc_free_client(client);
#endif
        return 0;
    }

    /* Create new bug in Bugzilla */

    if (!(opts & OPT_f))
    {
        struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
        if (!dd)
            xfunc_die();
        report_result_t *reported_to = find_in_reported_to(dd, "Bugzilla:");
        dd_close(dd);

        if (reported_to && reported_to->url)
        {
            char *msg = xasprintf("This problem was already reported to Bugzilla (see '%s')."
                            " Do you still want to create a new bug?",
                            reported_to->url);
            int yes = ask_yes_no(msg);
            free(msg);
            if (!yes)
                return 0;
        }
        free_report_result(reported_to);
    }

    problem_data_t *problem_data = create_problem_data_for_reporting(dump_dir_name);
    if (!problem_data)
        xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */

    const char *component = problem_data_get_content_or_die(problem_data, FILENAME_COMPONENT);
    const char *duphash   = problem_data_get_content_or_NULL(problem_data, FILENAME_DUPHASH);
//COMPAT, remove after 2.1 release
    if (!duphash) duphash = problem_data_get_content_or_die(problem_data, "global_uuid");

    if (!rhbz.b_product || !*rhbz.b_product) /* if not overridden or empty... */
    {
        free(rhbz.b_product);
        free(rhbz.b_product_version);
        map_string_t *osinfo = new_map_string();
        problem_data_get_osinfo(problem_data, osinfo);
        parse_osinfo_for_bz(osinfo, &rhbz.b_product, &rhbz.b_product_version);
        free_map_string(osinfo);

        if (!rhbz.b_product)
            error_msg_and_die(_("Can't determine Bugzilla Product from problem data."));
    }

    if (opts & OPT_D)
    {
        GList *comment_fmt_spec = load_bzrep_conf_file(fmt_file);
        struct strbuf *bzcomment_buf = strbuf_new();
        generate_bz_comment(bzcomment_buf, problem_data, comment_fmt_spec);
        char *bzcomment = strbuf_free_nobuf(bzcomment_buf);
        char *summary = create_summary_string(problem_data, comment_fmt_spec);
        printf("summary: %s\n"
                "\n"
                "%s"
                , summary, bzcomment
        );
        free(bzcomment);
        free(summary);
        exit(0);
    }

    login(client, &rhbz);


    int bug_id = 0;

    /* If REMOTE_RESULT contains "DUPLICATE 12345", we consider it a dup of 12345
     * and won't search on bz server.
     */
    char *remote_result;
    remote_result = problem_data_get_content_or_NULL(problem_data, FILENAME_REMOTE_RESULT);
    if (remote_result)
    {
        char *cmd = strtok(remote_result, " \n");
        char *id = strtok(NULL, " \n");

        if (!prefixcmp(cmd, "DUPLICATE"))
        {
            errno = 0;
            char *e;
            bug_id = strtoul(id, &e, 10);
            if (errno || id == e || *e != '\0' || bug_id > INT_MAX)
            {
                /* error / no digits / illegal trailing chars / too big a number */
                bug_id = 0;
            }
        }
    }

    struct bug_info *bz = NULL;
    if (!bug_id)
    {
        log(_("Checking for duplicates"));

        int existing_id = -1;
        int crossver_id = -1;
        {
            /* Figure out whether we want to match component
             * when doing dup search.
             */
            const char *component_substitute = is_in_comma_separated_list(component, rhbz.b_DontMatchComponents) ? NULL : component;

            /* We don't do dup detection across versions (see below why),
             * but we do add a note if cross-version potential dup exists.
             * For that, we search for cross version dups first:
             */
            xmlrpc_value *crossver_bugs = rhbz_search_duphash(client, rhbz.b_product, /*version:*/ NULL,
                            component_substitute, duphash);
            unsigned crossver_bugs_count = rhbz_array_size(crossver_bugs);
            VERB3 log("Bugzilla has %i reports with duphash '%s' including cross-version ones",
                    crossver_bugs_count, duphash);
            if (crossver_bugs_count > 0)
                crossver_id = rhbz_get_bug_id_from_array0(crossver_bugs, rhbz_ver);
            xmlrpc_DECREF(crossver_bugs);

            if (crossver_bugs_count > 0)
            {
                /* In dup detection we require match in product *and version*.
                 * Otherwise we sometimes have bugs in e.g. Fedora 17
                 * considered to be dups of Fedora 16 bugs.
                 * Imagine that F16 is "end-of-lifed" - allowing cross-version
                 * match will make all newly detected crashes DUPed
                 * to a bug in a dead release.
                 */
                xmlrpc_value *dup_bugs = rhbz_search_duphash(client, rhbz.b_product,
                                rhbz.b_product_version, component_substitute, duphash);
                unsigned dup_bugs_count = rhbz_array_size(dup_bugs);
                VERB3 log("Bugzilla has %i reports with duphash '%s'",
                        dup_bugs_count, duphash);
                if (dup_bugs_count > 0)
                    existing_id = rhbz_get_bug_id_from_array0(dup_bugs, rhbz_ver);
                xmlrpc_DECREF(dup_bugs);
            }
        }

        if (existing_id < 0)
        {
            /* Create new bug */
            log(_("Creating a new bug"));

            GList *comment_fmt_spec = load_bzrep_conf_file(fmt_file);

            struct strbuf *bzcomment_buf = strbuf_new();
            generate_bz_comment(bzcomment_buf, problem_data, comment_fmt_spec);
            if (crossver_id >= 0)
                strbuf_append_strf(bzcomment_buf, "\nPotential duplicate: bug %u\n", crossver_id);
            char *bzcomment = strbuf_free_nobuf(bzcomment_buf);
            char *summary = create_summary_string(problem_data, comment_fmt_spec);
            int new_id = rhbz_new_bug(client, problem_data, rhbz.b_product, rhbz.b_product_version,
                    summary, bzcomment,
                    group
            );
            free(bzcomment);
            free(summary);

            if (new_id == -1)
            {
                error_msg_and_die(_("Failed to create a new bug."));
            }

            log(_("Adding attachments to bug %i"), new_id);
            char new_id_str[sizeof(int)*3 + 2];
            sprintf(new_id_str, "%i", new_id);

            attach_files(client, new_id_str, problem_data, comment_fmt_spec);

//TODO: free_comment_fmt_spec(comment_fmt_spec);

            bz = new_bug_info();
            bz->bi_status = xstrdup("NEW");
            bz->bi_id = new_id;
            goto log_out;
        }

        bug_id = existing_id;
    }

    bz = rhbz_bug_info(client, bug_id);

    log(_("Bug is already reported: %i"), bz->bi_id);

    /* Follow duplicates */
    if ((strcmp(bz->bi_status, "CLOSED") == 0)
     && (strcmp(bz->bi_resolution, "DUPLICATE") == 0)
    ) {
        struct bug_info *origin;
        origin = rhbz_find_origin_bug_closed_duplicate(client, bz);
        if (origin)
        {
            free_bug_info(bz);
            bz = origin;
        }
    }

    if (strcmp(bz->bi_status, "CLOSED") != 0)
    {
        /* Add user's login to CC if not there already */
        if (strcmp(bz->bi_reporter, rhbz.b_login) != 0
         && !g_list_find_custom(bz->bi_cc_list, rhbz.b_login, (GCompareFunc)g_strcmp0)
        ) {
            log(_("Adding %s to CC list"), rhbz.b_login);
            rhbz_mail_to_cc(client, bz->bi_id, rhbz.b_login, RHBZ_NOMAIL_NOTIFY);
        }

        /* Add comment and bt */
        const char *comment = problem_data_get_content_or_NULL(problem_data, FILENAME_COMMENT);
        if (comment && comment[0])
        {
            GList *comment_fmt_spec = load_bzrep_conf_file(fmt_file2);
            struct strbuf *bzcomment_buf = strbuf_new();
            generate_bz_comment(bzcomment_buf, problem_data, comment_fmt_spec);
            char *bzcomment = strbuf_free_nobuf(bzcomment_buf);
//TODO: free_comment_fmt_spec(comment_fmt_spec);

            int dup_comment = is_comment_dup(bz->bi_comments, bzcomment);
            if (!dup_comment)
            {
                log(_("Adding new comment to bug %d"), bz->bi_id);
                rhbz_add_comment(client, bz->bi_id, bzcomment, 0);
                free(bzcomment);

                const char *bt = problem_data_get_content_or_NULL(problem_data, FILENAME_BACKTRACE);
                unsigned rating = 0;
                const char *rating_str = problem_data_get_content_or_NULL(problem_data, FILENAME_RATING);
                /* python doesn't have rating file */
                if (rating_str)
                    rating = xatou(rating_str);
                if (bt && rating > bz->bi_best_bt_rating)
                {
                    char bug_id_str[sizeof(int)*3 + 2];
                    sprintf(bug_id_str, "%i", bz->bi_id);
                    log(_("Attaching better backtrace"));
                    rhbz_attach_blob(client, bug_id_str, FILENAME_BACKTRACE, bt, strlen(bt),
                                     RHBZ_NOMAIL_NOTIFY);
                }
            }
            else
            {
                free(bzcomment);
                log(_("Found the same comment in the bug history, not adding a new one"));
            }
        }
    }

 log_out:
    log(_("Logging out"));
    rhbz_logout(client);

    log(_("Status: %s%s%s %s/show_bug.cgi?id=%u"),
                bz->bi_status,
                bz->bi_resolution ? " " : "",
                bz->bi_resolution ? bz->bi_resolution : "",
                rhbz.b_bugzilla_url,
                bz->bi_id);

    struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (dd)
    {
        char *msg = xasprintf("Bugzilla: URL=%s/show_bug.cgi?id=%u", rhbz.b_bugzilla_url, bz->bi_id);
        add_reported_to(dd, msg);
        free(msg);
        dd_close(dd);
    }

#if 0  /* enable if you search for leaks (valgrind etc) */
    free(rhbz.b_product);
    free(rhbz.b_product_version);
    problem_data_free(problem_data);
    free_bug_info(bz);
    abrt_xmlrpc_free_client(client);
#endif
    return 0;
}
Esempio n. 20
0
int microcom_main(int argc, char **argv)
{
	struct pollfd pfd[2];
#define sfd (pfd[1].fd)
	char *device_lock_file = NULL;
	const char *s;
	const char *opt_s = "9600";
	unsigned speed;
	int len;
	int exitcode = 1;
	struct termios tio0, tiosfd, tio;

	getopt32(argv, "s:", &opt_s);
	argc -= optind;
	argv += optind;
	if (!argv[0])
		bb_show_usage();
	speed = xatou(opt_s);

	// try to create lock file in /var/lock
	s = bb_basename(argv[0]);
	if (!s[0]) {
		errno = ENODEV;
		bb_perror_msg_and_die("can't lock device");
	}
	device_lock_file = xasprintf("/var/lock/LCK..%s", s);
	sfd = open(device_lock_file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644);
	if (sfd < 0) {
		if (ENABLE_FEATURE_CLEAN_UP)
			free(device_lock_file);
		device_lock_file = NULL;
		if (errno == EEXIST)
			bb_perror_msg_and_die("can't lock device");
		// We don't abort on other errors: /var/lock can be
		// non-writable or non-existent
	} else {
		// %4d to make mgetty happy. It treats 4-bytes lock files as binary,
		// not text, PID. Making 5+ char file. Brrr...
		s = xasprintf("%4d\n", getpid());
		write(sfd, s, strlen(s));
		if (ENABLE_FEATURE_CLEAN_UP)
			free((char*)s);
		close(sfd);
	}

	// open device
	sfd = open(argv[0], O_RDWR);
	if (sfd < 0) {
		bb_perror_msg("can't open device");
		goto unlock_and_exit;
	}

	// put stdin to "raw mode", handle one character at a time
	tcgetattr(STDIN_FILENO, &tio0);
	tio = tio0;
	tio.c_lflag &= ~(ICANON|ECHO);
	tio.c_iflag &= ~(IXON|ICRNL);
	tio.c_oflag &= ~(ONLCR);
	tio.c_cc[VMIN] = 1;
	tio.c_cc[VTIME] = 0;
	if (tcsetattr(STDIN_FILENO, TCSANOW, &tio)) {
		bb_perror_msg("can't tcsetattr for %s", "stdin");
		goto unlock_and_exit;
	}

	/* same thing for modem (plus: set baud rate) - TODO: make CLI option */
	tcgetattr(sfd, &tiosfd);
	tio = tiosfd;
	tio.c_lflag &= ~(ICANON|ECHO);
	tio.c_iflag &= ~(IXON|ICRNL);
	tio.c_oflag &= ~(ONLCR);
	tio.c_cc[VMIN] = 1;
	tio.c_cc[VTIME] = 0;
	cfsetispeed(&tio, tty_value_to_baud(speed));
	cfsetospeed(&tio, tty_value_to_baud(speed));
	if (tcsetattr(sfd, TCSANOW, &tio)) {
		bb_perror_msg("can't tcsetattr for %s", "device");
		goto unlock_and_exit;
	}

	// disable SIGINT
	signal(SIGINT, SIG_IGN);

	// drain stdin
	tcflush(STDIN_FILENO, TCIFLUSH);
	printf("connected to '%s' (%d bps), exit with ctrl-X...\r\n", argv[0], speed);

	// main loop: check with poll(), then read/write bytes across
	pfd[0].fd = STDIN_FILENO;
	pfd[0].events = POLLIN;
	/*pfd[1].fd = sfd;*/
	pfd[1].events = POLLIN;
	while (1) {
		int i;
		safe_poll(pfd, 2, -1);
		for (i = 0; i < 2; ++i) {
			if (pfd[i].revents & POLLIN) {
				len = read(pfd[i].fd, bb_common_bufsiz1, COMMON_BUFSIZE);
				if (len > 0) {
					if (!i && 24 == bb_common_bufsiz1[0])
						goto done; // ^X exits
					write(pfd[1-i].fd, bb_common_bufsiz1, len);
				}
			}
		}
	}
 done:
	tcsetattr(sfd, TCSANOW, &tiosfd);
	tcsetattr(STDIN_FILENO, TCSANOW, &tio0);
	tcflush(STDIN_FILENO, TCIFLUSH);

	if (ENABLE_FEATURE_CLEAN_UP)
		close(sfd);
	exitcode = 0;

 unlock_and_exit:
	// delete lock file
	if (device_lock_file) {
		unlink(device_lock_file);
		if (ENABLE_FEATURE_CLEAN_UP)
			free(device_lock_file);
	}
	return exitcode;
}
Esempio n. 21
0
static tcflag_t *get_ptr_to_tcflag(unsigned type, const struct termios *mode)
{
	static const uint8_t tcflag_offsets[] ALIGN1 = {
		offsetof(struct termios, c_cflag), /* control */
		offsetof(struct termios, c_iflag), /* input */
		offsetof(struct termios, c_oflag), /* output */
		offsetof(struct termios, c_lflag)  /* local */
	};
	if (type <= local) {
		return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]);
	}
	return NULL;
}

/* Flags for 'struct mode_info' */
#define SANE_SET 1              /* Set in 'sane' mode                  */
#define SANE_UNSET 2            /* Unset in 'sane' mode                */
#define REV 4                   /* Can be turned off by prepending '-' */
#define OMIT 8                  /* Don't display value                 */


/* Each mode.
 * This structure should be kept as small as humanly possible.
 */
struct mode_info {
	const uint8_t type;           /* Which structure element to change    */
	const uint8_t flags;          /* Setting and display options          */
	/* only these values are ever used, so... */
#if   (CSIZE | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY) < 0x100
	const uint8_t mask;
#elif (CSIZE | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY) < 0x10000
	const uint16_t mask;
#else
	const tcflag_t mask;          /* Other bits to turn off for this mode */
#endif
	/* was using short here, but ppc32 was unhappy */
	const tcflag_t bits;          /* Bits to set for this mode            */
};

enum {
	/* Must match mode_name[] and mode_info[] order! */
	IDX_evenp = 0,
	IDX_parity,
	IDX_oddp,
	IDX_nl,
	IDX_ek,
	IDX_sane,
	IDX_cooked,
	IDX_raw,
	IDX_pass8,
	IDX_litout,
	IDX_cbreak,
	IDX_crt,
	IDX_dec,
#if IXANY
	IDX_decctlq,
#endif
#if TABDLY || OXTABS
	IDX_tabs,
#endif
#if XCASE && IUCLC && OLCUC
	IDX_lcase,
	IDX_LCASE,
#endif
};

#define MI_ENTRY(N,T,F,B,M) N "\0"

/* Mode names given on command line */
static const char mode_name[] =
	MI_ENTRY("evenp",    combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("parity",   combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("oddp",     combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("nl",       combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("ek",       combination, OMIT,              0,          0 )
	MI_ENTRY("sane",     combination, OMIT,              0,          0 )
	MI_ENTRY("cooked",   combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("raw",      combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("pass8",    combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("litout",   combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("cbreak",   combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("crt",      combination, OMIT,              0,          0 )
	MI_ENTRY("dec",      combination, OMIT,              0,          0 )
#if IXANY
	MI_ENTRY("decctlq",  combination, REV        | OMIT, 0,          0 )
#endif
#if TABDLY || OXTABS
	MI_ENTRY("tabs",     combination, REV        | OMIT, 0,          0 )
#endif
#if XCASE && IUCLC && OLCUC
	MI_ENTRY("lcase",    combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("LCASE",    combination, REV        | OMIT, 0,          0 )
#endif
	MI_ENTRY("parenb",   control,     REV,               PARENB,     0 )
	MI_ENTRY("parodd",   control,     REV,               PARODD,     0 )
	MI_ENTRY("cs5",      control,     0,                 CS5,     CSIZE)
	MI_ENTRY("cs6",      control,     0,                 CS6,     CSIZE)
	MI_ENTRY("cs7",      control,     0,                 CS7,     CSIZE)
	MI_ENTRY("cs8",      control,     0,                 CS8,     CSIZE)
	MI_ENTRY("hupcl",    control,     REV,               HUPCL,      0 )
	MI_ENTRY("hup",      control,     REV        | OMIT, HUPCL,      0 )
	MI_ENTRY("cstopb",   control,     REV,               CSTOPB,     0 )
	MI_ENTRY("cread",    control,     SANE_SET   | REV,  CREAD,      0 )
	MI_ENTRY("clocal",   control,     REV,               CLOCAL,     0 )
#if CRTSCTS
	MI_ENTRY("crtscts",  control,     REV,               CRTSCTS,    0 )
#endif
	MI_ENTRY("ignbrk",   input,       SANE_UNSET | REV,  IGNBRK,     0 )
	MI_ENTRY("brkint",   input,       SANE_SET   | REV,  BRKINT,     0 )
	MI_ENTRY("ignpar",   input,       REV,               IGNPAR,     0 )
	MI_ENTRY("parmrk",   input,       REV,               PARMRK,     0 )
	MI_ENTRY("inpck",    input,       REV,               INPCK,      0 )
	MI_ENTRY("istrip",   input,       REV,               ISTRIP,     0 )
	MI_ENTRY("inlcr",    input,       SANE_UNSET | REV,  INLCR,      0 )
	MI_ENTRY("igncr",    input,       SANE_UNSET | REV,  IGNCR,      0 )
	MI_ENTRY("icrnl",    input,       SANE_SET   | REV,  ICRNL,      0 )
	MI_ENTRY("ixon",     input,       REV,               IXON,       0 )
	MI_ENTRY("ixoff",    input,       SANE_UNSET | REV,  IXOFF,      0 )
	MI_ENTRY("tandem",   input,       OMIT       | REV,  IXOFF,      0 )
#if IUCLC
	MI_ENTRY("iuclc",    input,       SANE_UNSET | REV,  IUCLC,      0 )
#endif
#if IXANY
	MI_ENTRY("ixany",    input,       SANE_UNSET | REV,  IXANY,      0 )
#endif
#if IMAXBEL
	MI_ENTRY("imaxbel",  input,       SANE_SET   | REV,  IMAXBEL,    0 )
#endif
#if IUTF8
	MI_ENTRY("iutf8",    input,       SANE_UNSET | REV,  IUTF8,      0 )
#endif
	MI_ENTRY("opost",    output,      SANE_SET   | REV,  OPOST,      0 )
#if OLCUC
	MI_ENTRY("olcuc",    output,      SANE_UNSET | REV,  OLCUC,      0 )
#endif
#if OCRNL
	MI_ENTRY("ocrnl",    output,      SANE_UNSET | REV,  OCRNL,      0 )
#endif
#if ONLCR
	MI_ENTRY("onlcr",    output,      SANE_SET   | REV,  ONLCR,      0 )
#endif
#if ONOCR
	MI_ENTRY("onocr",    output,      SANE_UNSET | REV,  ONOCR,      0 )
#endif
#if ONLRET
	MI_ENTRY("onlret",   output,      SANE_UNSET | REV,  ONLRET,     0 )
#endif
#if OFILL
	MI_ENTRY("ofill",    output,      SANE_UNSET | REV,  OFILL,      0 )
#endif
#if OFDEL
	MI_ENTRY("ofdel",    output,      SANE_UNSET | REV,  OFDEL,      0 )
#endif
#if NLDLY
	MI_ENTRY("nl1",      output,      SANE_UNSET,        NL1,     NLDLY)
	MI_ENTRY("nl0",      output,      SANE_SET,          NL0,     NLDLY)
#endif
#if CRDLY
	MI_ENTRY("cr3",      output,      SANE_UNSET,        CR3,     CRDLY)
	MI_ENTRY("cr2",      output,      SANE_UNSET,        CR2,     CRDLY)
	MI_ENTRY("cr1",      output,      SANE_UNSET,        CR1,     CRDLY)
	MI_ENTRY("cr0",      output,      SANE_SET,          CR0,     CRDLY)
#endif

#if TABDLY
	MI_ENTRY("tab3",     output,      SANE_UNSET,        TAB3,   TABDLY)
# if TAB2
	MI_ENTRY("tab2",     output,      SANE_UNSET,        TAB2,   TABDLY)
# endif
# if TAB1
	MI_ENTRY("tab1",     output,      SANE_UNSET,        TAB1,   TABDLY)
# endif
	MI_ENTRY("tab0",     output,      SANE_SET,          TAB0,   TABDLY)
#else
# if OXTABS
	MI_ENTRY("tab3",     output,      SANE_UNSET,        OXTABS,     0 )
# endif
#endif

#if BSDLY
	MI_ENTRY("bs1",      output,      SANE_UNSET,        BS1,     BSDLY)
	MI_ENTRY("bs0",      output,      SANE_SET,          BS0,     BSDLY)
#endif
#if VTDLY
	MI_ENTRY("vt1",      output,      SANE_UNSET,        VT1,     VTDLY)
	MI_ENTRY("vt0",      output,      SANE_SET,          VT0,     VTDLY)
#endif
#if FFDLY
	MI_ENTRY("ff1",      output,      SANE_UNSET,        FF1,     FFDLY)
	MI_ENTRY("ff0",      output,      SANE_SET,          FF0,     FFDLY)
#endif
	MI_ENTRY("isig",     local,       SANE_SET   | REV,  ISIG,       0 )
	MI_ENTRY("icanon",   local,       SANE_SET   | REV,  ICANON,     0 )
#if IEXTEN
	MI_ENTRY("iexten",   local,       SANE_SET   | REV,  IEXTEN,     0 )
#endif
	MI_ENTRY("echo",     local,       SANE_SET   | REV,  ECHO,       0 )
	MI_ENTRY("echoe",    local,       SANE_SET   | REV,  ECHOE,      0 )
	MI_ENTRY("crterase", local,       OMIT       | REV,  ECHOE,      0 )
	MI_ENTRY("echok",    local,       SANE_SET   | REV,  ECHOK,      0 )
	MI_ENTRY("echonl",   local,       SANE_UNSET | REV,  ECHONL,     0 )
	MI_ENTRY("noflsh",   local,       SANE_UNSET | REV,  NOFLSH,     0 )
#if XCASE
	MI_ENTRY("xcase",    local,       SANE_UNSET | REV,  XCASE,      0 )
#endif
#if TOSTOP
	MI_ENTRY("tostop",   local,       SANE_UNSET | REV,  TOSTOP,     0 )
#endif
#if ECHOPRT
	MI_ENTRY("echoprt",  local,       SANE_UNSET | REV,  ECHOPRT,    0 )
	MI_ENTRY("prterase", local,       OMIT       | REV,  ECHOPRT,    0 )
#endif
#if ECHOCTL
	MI_ENTRY("echoctl",  local,       SANE_SET   | REV,  ECHOCTL,    0 )
	MI_ENTRY("ctlecho",  local,       OMIT       | REV,  ECHOCTL,    0 )
#endif
#if ECHOKE
	MI_ENTRY("echoke",   local,       SANE_SET   | REV,  ECHOKE,     0 )
	MI_ENTRY("crtkill",  local,       OMIT       | REV,  ECHOKE,     0 )
#endif
	;

#undef MI_ENTRY
#define MI_ENTRY(N,T,F,B,M) { T, F, M, B },

static const struct mode_info mode_info[] = {
	/* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */
	MI_ENTRY("evenp",    combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("parity",   combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("oddp",     combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("nl",       combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("ek",       combination, OMIT,              0,          0 )
	MI_ENTRY("sane",     combination, OMIT,              0,          0 )
	MI_ENTRY("cooked",   combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("raw",      combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("pass8",    combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("litout",   combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("cbreak",   combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("crt",      combination, OMIT,              0,          0 )
	MI_ENTRY("dec",      combination, OMIT,              0,          0 )
#if IXANY
	MI_ENTRY("decctlq",  combination, REV        | OMIT, 0,          0 )
#endif
#if TABDLY || OXTABS
	MI_ENTRY("tabs",     combination, REV        | OMIT, 0,          0 )
#endif
#if XCASE && IUCLC && OLCUC
	MI_ENTRY("lcase",    combination, REV        | OMIT, 0,          0 )
	MI_ENTRY("LCASE",    combination, REV        | OMIT, 0,          0 )
#endif
	MI_ENTRY("parenb",   control,     REV,               PARENB,     0 )
	MI_ENTRY("parodd",   control,     REV,               PARODD,     0 )
	MI_ENTRY("cs5",      control,     0,                 CS5,     CSIZE)
	MI_ENTRY("cs6",      control,     0,                 CS6,     CSIZE)
	MI_ENTRY("cs7",      control,     0,                 CS7,     CSIZE)
	MI_ENTRY("cs8",      control,     0,                 CS8,     CSIZE)
	MI_ENTRY("hupcl",    control,     REV,               HUPCL,      0 )
	MI_ENTRY("hup",      control,     REV        | OMIT, HUPCL,      0 )
	MI_ENTRY("cstopb",   control,     REV,               CSTOPB,     0 )
	MI_ENTRY("cread",    control,     SANE_SET   | REV,  CREAD,      0 )
	MI_ENTRY("clocal",   control,     REV,               CLOCAL,     0 )
#if CRTSCTS
	MI_ENTRY("crtscts",  control,     REV,               CRTSCTS,    0 )
#endif
	MI_ENTRY("ignbrk",   input,       SANE_UNSET | REV,  IGNBRK,     0 )
	MI_ENTRY("brkint",   input,       SANE_SET   | REV,  BRKINT,     0 )
	MI_ENTRY("ignpar",   input,       REV,               IGNPAR,     0 )
	MI_ENTRY("parmrk",   input,       REV,               PARMRK,     0 )
	MI_ENTRY("inpck",    input,       REV,               INPCK,      0 )
	MI_ENTRY("istrip",   input,       REV,               ISTRIP,     0 )
	MI_ENTRY("inlcr",    input,       SANE_UNSET | REV,  INLCR,      0 )
	MI_ENTRY("igncr",    input,       SANE_UNSET | REV,  IGNCR,      0 )
	MI_ENTRY("icrnl",    input,       SANE_SET   | REV,  ICRNL,      0 )
	MI_ENTRY("ixon",     input,       REV,               IXON,       0 )
	MI_ENTRY("ixoff",    input,       SANE_UNSET | REV,  IXOFF,      0 )
	MI_ENTRY("tandem",   input,       OMIT       | REV,  IXOFF,      0 )
#if IUCLC
	MI_ENTRY("iuclc",    input,       SANE_UNSET | REV,  IUCLC,      0 )
#endif
#if IXANY
	MI_ENTRY("ixany",    input,       SANE_UNSET | REV,  IXANY,      0 )
#endif
#if IMAXBEL
	MI_ENTRY("imaxbel",  input,       SANE_SET   | REV,  IMAXBEL,    0 )
#endif
#if IUTF8
	MI_ENTRY("iutf8",    input,       SANE_UNSET | REV,  IUTF8,      0 )
#endif
	MI_ENTRY("opost",    output,      SANE_SET   | REV,  OPOST,      0 )
#if OLCUC
	MI_ENTRY("olcuc",    output,      SANE_UNSET | REV,  OLCUC,      0 )
#endif
#if OCRNL
	MI_ENTRY("ocrnl",    output,      SANE_UNSET | REV,  OCRNL,      0 )
#endif
#if ONLCR
	MI_ENTRY("onlcr",    output,      SANE_SET   | REV,  ONLCR,      0 )
#endif
#if ONOCR
	MI_ENTRY("onocr",    output,      SANE_UNSET | REV,  ONOCR,      0 )
#endif
#if ONLRET
	MI_ENTRY("onlret",   output,      SANE_UNSET | REV,  ONLRET,     0 )
#endif
#if OFILL
	MI_ENTRY("ofill",    output,      SANE_UNSET | REV,  OFILL,      0 )
#endif
#if OFDEL
	MI_ENTRY("ofdel",    output,      SANE_UNSET | REV,  OFDEL,      0 )
#endif
#if NLDLY
	MI_ENTRY("nl1",      output,      SANE_UNSET,        NL1,     NLDLY)
	MI_ENTRY("nl0",      output,      SANE_SET,          NL0,     NLDLY)
#endif
#if CRDLY
	MI_ENTRY("cr3",      output,      SANE_UNSET,        CR3,     CRDLY)
	MI_ENTRY("cr2",      output,      SANE_UNSET,        CR2,     CRDLY)
	MI_ENTRY("cr1",      output,      SANE_UNSET,        CR1,     CRDLY)
	MI_ENTRY("cr0",      output,      SANE_SET,          CR0,     CRDLY)
#endif

#if TABDLY
	MI_ENTRY("tab3",     output,      SANE_UNSET,        TAB3,   TABDLY)
# if TAB2
	MI_ENTRY("tab2",     output,      SANE_UNSET,        TAB2,   TABDLY)
# endif
# if TAB1
	MI_ENTRY("tab1",     output,      SANE_UNSET,        TAB1,   TABDLY)
# endif
	MI_ENTRY("tab0",     output,      SANE_SET,          TAB0,   TABDLY)
#else
# if OXTABS
	MI_ENTRY("tab3",     output,      SANE_UNSET,        OXTABS,     0 )
# endif
#endif

#if BSDLY
	MI_ENTRY("bs1",      output,      SANE_UNSET,        BS1,     BSDLY)
	MI_ENTRY("bs0",      output,      SANE_SET,          BS0,     BSDLY)
#endif
#if VTDLY
	MI_ENTRY("vt1",      output,      SANE_UNSET,        VT1,     VTDLY)
	MI_ENTRY("vt0",      output,      SANE_SET,          VT0,     VTDLY)
#endif
#if FFDLY
	MI_ENTRY("ff1",      output,      SANE_UNSET,        FF1,     FFDLY)
	MI_ENTRY("ff0",      output,      SANE_SET,          FF0,     FFDLY)
#endif
	MI_ENTRY("isig",     local,       SANE_SET   | REV,  ISIG,       0 )
	MI_ENTRY("icanon",   local,       SANE_SET   | REV,  ICANON,     0 )
#if IEXTEN
	MI_ENTRY("iexten",   local,       SANE_SET   | REV,  IEXTEN,     0 )
#endif
	MI_ENTRY("echo",     local,       SANE_SET   | REV,  ECHO,       0 )
	MI_ENTRY("echoe",    local,       SANE_SET   | REV,  ECHOE,      0 )
	MI_ENTRY("crterase", local,       OMIT       | REV,  ECHOE,      0 )
	MI_ENTRY("echok",    local,       SANE_SET   | REV,  ECHOK,      0 )
	MI_ENTRY("echonl",   local,       SANE_UNSET | REV,  ECHONL,     0 )
	MI_ENTRY("noflsh",   local,       SANE_UNSET | REV,  NOFLSH,     0 )
#if XCASE
	MI_ENTRY("xcase",    local,       SANE_UNSET | REV,  XCASE,      0 )
#endif
#if TOSTOP
	MI_ENTRY("tostop",   local,       SANE_UNSET | REV,  TOSTOP,     0 )
#endif
#if ECHOPRT
	MI_ENTRY("echoprt",  local,       SANE_UNSET | REV,  ECHOPRT,    0 )
	MI_ENTRY("prterase", local,       OMIT       | REV,  ECHOPRT,    0 )
#endif
#if ECHOCTL
	MI_ENTRY("echoctl",  local,       SANE_SET   | REV,  ECHOCTL,    0 )
	MI_ENTRY("ctlecho",  local,       OMIT       | REV,  ECHOCTL,    0 )
#endif
#if ECHOKE
	MI_ENTRY("echoke",   local,       SANE_SET   | REV,  ECHOKE,     0 )
	MI_ENTRY("crtkill",  local,       OMIT       | REV,  ECHOKE,     0 )
#endif
};

enum {
	NUM_mode_info = ARRAY_SIZE(mode_info)
};


/* Control characters */
struct control_info {
	const uint8_t saneval;  /* Value to set for 'stty sane' */
	const uint8_t offset;   /* Offset in c_cc */
};

enum {
	/* Must match control_name[] and control_info[] order! */
	CIDX_intr = 0,
	CIDX_quit,
	CIDX_erase,
	CIDX_kill,
	CIDX_eof,
	CIDX_eol,
#if VEOL2
	CIDX_eol2,
#endif
#if VSWTCH
	CIDX_swtch,
#endif
	CIDX_start,
	CIDX_stop,
	CIDX_susp,
#if VDSUSP
	CIDX_dsusp,
#endif
#if VREPRINT
	CIDX_rprnt,
#endif
#if VWERASE
	CIDX_werase,
#endif
#if VLNEXT
	CIDX_lnext,
#endif
#if VFLUSHO
	CIDX_flush,
#endif
#if VSTATUS
	CIDX_status,
#endif
	CIDX_min,
	CIDX_time,
};

#define CI_ENTRY(n,s,o) n "\0"

/* Name given on command line */
static const char control_name[] =
	CI_ENTRY("intr",     CINTR,   VINTR   )
	CI_ENTRY("quit",     CQUIT,   VQUIT   )
	CI_ENTRY("erase",    CERASE,  VERASE  )
	CI_ENTRY("kill",     CKILL,   VKILL   )
	CI_ENTRY("eof",      CEOF,    VEOF    )
	CI_ENTRY("eol",      CEOL,    VEOL    )
#if VEOL2
	CI_ENTRY("eol2",     CEOL2,   VEOL2   )
#endif
#if VSWTCH
	CI_ENTRY("swtch",    CSWTCH,  VSWTCH  )
#endif
	CI_ENTRY("start",    CSTART,  VSTART  )
	CI_ENTRY("stop",     CSTOP,   VSTOP   )
	CI_ENTRY("susp",     CSUSP,   VSUSP   )
#if VDSUSP
	CI_ENTRY("dsusp",    CDSUSP,  VDSUSP  )
#endif
#if VREPRINT
	CI_ENTRY("rprnt",    CRPRNT,  VREPRINT)
#endif
#if VWERASE
	CI_ENTRY("werase",   CWERASE, VWERASE )
#endif
#if VLNEXT
	CI_ENTRY("lnext",    CLNEXT,  VLNEXT  )
#endif
#if VFLUSHO
	CI_ENTRY("flush",    CFLUSHO, VFLUSHO )
#endif
#if VSTATUS
	CI_ENTRY("status",   CSTATUS, VSTATUS )
#endif
	/* These must be last because of the display routines */
	CI_ENTRY("min",      1,       VMIN    )
	CI_ENTRY("time",     0,       VTIME   )
	;

#undef CI_ENTRY
#define CI_ENTRY(n,s,o) { s, o },

static const struct control_info control_info[] = {
	/* This should be verbatim cut-n-paste copy of the above CI_ENTRYs */
	CI_ENTRY("intr",     CINTR,   VINTR   )
	CI_ENTRY("quit",     CQUIT,   VQUIT   )
	CI_ENTRY("erase",    CERASE,  VERASE  )
	CI_ENTRY("kill",     CKILL,   VKILL   )
	CI_ENTRY("eof",      CEOF,    VEOF    )
	CI_ENTRY("eol",      CEOL,    VEOL    )
#if VEOL2
	CI_ENTRY("eol2",     CEOL2,   VEOL2   )
#endif
#if VSWTCH
	CI_ENTRY("swtch",    CSWTCH,  VSWTCH  )
#endif
	CI_ENTRY("start",    CSTART,  VSTART  )
	CI_ENTRY("stop",     CSTOP,   VSTOP   )
	CI_ENTRY("susp",     CSUSP,   VSUSP   )
#if VDSUSP
	CI_ENTRY("dsusp",    CDSUSP,  VDSUSP  )
#endif
#if VREPRINT
	CI_ENTRY("rprnt",    CRPRNT,  VREPRINT)
#endif
#if VWERASE
	CI_ENTRY("werase",   CWERASE, VWERASE )
#endif
#if VLNEXT
	CI_ENTRY("lnext",    CLNEXT,  VLNEXT  )
#endif
#if VFLUSHO
	CI_ENTRY("flush",    CFLUSHO, VFLUSHO )
#endif
#if VSTATUS
	CI_ENTRY("status",   CSTATUS, VSTATUS )
#endif
	/* These must be last because of the display routines */
	CI_ENTRY("min",      1,       VMIN    )
	CI_ENTRY("time",     0,       VTIME   )
};

enum {
	NUM_control_info = ARRAY_SIZE(control_info)
};


struct globals {
	const char *device_name;
	/* The width of the screen, for output wrapping */
	unsigned max_col;
	/* Current position, to know when to wrap */
	unsigned current_col;
	char buf[10];
} FIX_ALIASING;
#define G (*(struct globals*)&bb_common_bufsiz1)
#define INIT_G() do { \
	G.device_name = bb_msg_standard_input; \
	G.max_col = 80; \
} while (0)

static void set_speed_or_die(enum speed_setting type, const char *arg,
					struct termios *mode)
{
	speed_t baud;

	baud = tty_value_to_baud(xatou(arg));

	if (type != output_speed) {     /* either input or both */
		cfsetispeed(mode, baud);
	}
	if (type != input_speed) {      /* either output or both */
		cfsetospeed(mode, baud);
	}
}
Esempio n. 22
0
int arping_main(int argc, char **argv)
{
	const char *device = "eth0";
	int ifindex;
	char *source = NULL;
	char *target;

	s = xsocket(PF_PACKET, SOCK_DGRAM, 0);

	// Drop suid root privileges
	xsetuid(getuid());

	{
		unsigned opt;
		char *_count, *_timeout;

		/* Dad also sets quit_on_reply.
		 * Advert also sets unsolicited.
		 */
		opt_complementary = "Df:AU";
		opt = getopt32(argc, argv, "DUAqfbc:w:i:s:",
					&_count, &_timeout, &device, &source);
		cfg |= opt & 0x3f; /* set respective flags */
		if (opt & 0x40) /* -c: count */
			count = xatou(_count);
		if (opt & 0x80) /* -w: timeout */
			timeout = xatoul_range(_timeout, 0, INT_MAX/2000);
		//if (opt & 0x100) /* -i: interface */
		if (strlen(device) > IF_NAMESIZE) {
			bb_error_msg_and_die("interface name '%s' is too long",
							device);
		}
		//if (opt & 0x200) /* -s: source */
	}
	argc -= optind;
	argv += optind;

	if (argc != 1)
		bb_show_usage();

	target = *argv;

	xfunc_error_retval = 2;

	{
		struct ifreq ifr;

		memset(&ifr, 0, sizeof(ifr));
		strncpy(ifr.ifr_name, device, IFNAMSIZ - 1);
		if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
			bb_error_msg_and_die("interface %s not found", device);
		}
		ifindex = ifr.ifr_ifindex;

		if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) {
			bb_error_msg_and_die("SIOCGIFFLAGS");
		}
		if (!(ifr.ifr_flags & IFF_UP)) {
			bb_error_msg_and_die("interface %s is down", device);
		}
		if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {
			bb_error_msg("interface %s is not ARPable", device);
			return (cfg & dad ? 0 : 2);
		}
	}

	if (!inet_aton(target, &dst)) {
		len_and_sockaddr *lsa;
		lsa = xhost_and_af2sockaddr(target, 0, AF_INET);
		memcpy(&dst, &lsa->sin.sin_addr.s_addr, 4);
		if (ENABLE_FEATURE_CLEAN_UP)
			free(lsa);
	}

	if (source && !inet_aton(source, &src)) {
		bb_error_msg_and_die("invalid source address %s", source);
	}

	if (!(cfg & dad) && (cfg & unsolicited) && src.s_addr == 0)
		src = dst;

	if (!(cfg & dad) || src.s_addr) {
		struct sockaddr_in saddr;
		int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);

		if (device) {
			if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1)
				bb_error_msg("warning: interface %s is ignored", device);
		}
		memset(&saddr, 0, sizeof(saddr));
		saddr.sin_family = AF_INET;
		if (src.s_addr) {
			saddr.sin_addr = src;
			xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
		} else if (!(cfg & dad)) {
			socklen_t alen = sizeof(saddr);

			saddr.sin_port = htons(1025);
			saddr.sin_addr = dst;

			if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1)
				bb_perror_msg("warning: setsockopt(SO_DONTROUTE)");
			xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
			if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) {
				bb_error_msg_and_die("getsockname");
			}
			src = saddr.sin_addr;
		}
		close(probe_fd);
	}

	me.sll_family = AF_PACKET;
	me.sll_ifindex = ifindex;
	me.sll_protocol = htons(ETH_P_ARP);
	xbind(s, (struct sockaddr *) &me, sizeof(me));

	{
		socklen_t alen = sizeof(me);

		if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) {
			bb_error_msg_and_die("getsockname");
		}
	}
	if (me.sll_halen == 0) {
		bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device);
		return (cfg & dad ? 0 : 2);
	}
	he = me;
	memset(he.sll_addr, -1, he.sll_halen);

	if (!(cfg & quiet)) {
		printf("ARPING to %s from %s via %s\n",
			inet_ntoa(dst), inet_ntoa(src),
			device ? device : "unknown");
	}

	if (!src.s_addr && !(cfg & dad)) {
		bb_error_msg_and_die("no src address in the non-DAD mode");
	}

	{
		struct sigaction sa;

		memset(&sa, 0, sizeof(sa));
		sa.sa_flags = SA_RESTART;

		sa.sa_handler = (void (*)(int)) finish;
		sigaction(SIGINT, &sa, NULL);

		sa.sa_handler = (void (*)(int)) catcher;
		sigaction(SIGALRM, &sa, NULL);
	}

	catcher();

	while (1) {
		sigset_t sset, osset;
		RESERVE_CONFIG_UBUFFER(packet, 4096);
		struct sockaddr_ll from;
		socklen_t alen = sizeof(from);
		int cc;

		cc = recvfrom(s, packet, 4096, 0, (struct sockaddr *) &from, &alen);
		if (cc < 0) {
			bb_perror_msg("recvfrom");
			continue;
		}
		sigemptyset(&sset);
		sigaddset(&sset, SIGALRM);
		sigaddset(&sset, SIGINT);
		sigprocmask(SIG_BLOCK, &sset, &osset);
		recv_pack(packet, cc, &from);
		sigprocmask(SIG_SETMASK, &osset, NULL);
		RELEASE_CONFIG_BUFFER(packet);
	}
}
Esempio n. 23
0
/*

     Parse Threshold Rule option parameters for each RULE

     'threshold: type limit|threshold|both, track by_src|by_dst, count #, seconds #;'

*/
void ParseThreshold2( THDX_STRUCT * thdx, char * s )
{
      int    i = 0;
      char * argv[100], * t;
      int    argc;
      int    count_flag=0;
      int    seconds_flag=0;
      int    type_flag=0;
      int    tracking_flag=0;
      
      if( !s_enabled )
          return ;

      memset( thdx, 0, sizeof(THDX_STRUCT) );

      thdx->priority = -1; /* Make this lower than standalone threshold command defaults ??? */
      
      /* Parse all of the args - they come in pairs */      
      for( argc=0, t = strtok(s," ,\n");  argc < 100 &&  t != 0 ;  argc++, t = strtok(0," ,\n") )
      {
          argv[ argc ] = t;           
      }

      /* Parameter Check - enough args ?*/
      if( argc != 8 )
      {
          /* Fatal incorrect argument count */ 
          FatalError("Threshold-RuleOptionParse: incorrect argument count, should be 4 pairs\n");
      }

      for(i=0;i<argc;i++)
      {
        if( strcmp(argv[i],"count") == 0  )
         {
            i++;
            thdx->count = xatou(argv[i],"threshold: count");
            count_flag++;
         }
        else if( strcmp(argv[i],"seconds") == 0  )
         {
            i++;
            thdx->seconds = xatou(argv[i],"threshold: seconds");
            seconds_flag++;
         }
        else if( strcmp(argv[i],"type") == 0  )
         {
            i++;
            if( strcmp(argv[i],"limit") == 0 )
            {
               thdx->type = THD_TYPE_LIMIT;
            }
            else if( strcmp(argv[i],"threshold") == 0 )
            {
               thdx->type = THD_TYPE_THRESHOLD;
            }
            else if( strcmp(argv[i],"both") == 0 )
            {
               thdx->type = THD_TYPE_BOTH;
            }
            else
            {
                /* Fatal incorrect threshold type */
                 FatalError("Threshold-RuleOptionParse: incorrect 'type' argument \n");
            }
            type_flag++;
         }
        else if( strcmp(argv[i],"track") == 0  )
         {
            i++;
            if( strcmp(argv[i],"by_src") == 0 )
            {
                thdx->tracking = THD_TRK_SRC;
            }
            else if( strcmp(argv[i],"by_dst") == 0 )
            {
                thdx->tracking = THD_TRK_DST;
            }
            else
            {
                /* Fatal incorrect threshold type */
                 FatalError("Threshold-RuleOptionParse: incorrect tracking type\n");
            }
            tracking_flag++;
         }
        else
         {
            /* Fatal Out Here - Unknow Option */
            FatalError("Threshold-RuleOptionParse: unknown argument \n");
         }
     }

     if( (count_flag + tracking_flag + type_flag + seconds_flag ) != 4 )
     {
         /* Fatal - incorrect argument count */
         FatalError("Threshold-RuleOptionParse: incorrect argument count\n");
     }
}
Esempio n. 24
0
/*
   threshold gen_id #, sig_id #, type limit|threshold|both, track by_src|by_dst,  count #, seconds #

   8/25/03 - added support for a global threshold, uses sid = 0, and is applied after all other thresholding so 
   a sid specific threshold or suppress command has precedence...
*/
void ParseSFThreshold( FILE * fp, char * rule )
{
     char        **args, **oargs;
     int         nargs, noargs;
     THDX_STRUCT thdx;
     int         count_flag=0;
     int         seconds_flag=0;
     int         type_flag=0;
     int         tracking_flag=0;
/*     
     int         priority_flag=0;
*/
     int         genid_flag=0;
     int         sigid_flag=0;
     int         i;

     memset( &thdx, 0, sizeof(THDX_STRUCT) );

     while( (*rule <= ' ') && (*rule > 0) ) rule++; /* skip whitespace */
     while( (*rule  > ' ') ) rule++;  /* skip 'threshold' */

     args = mSplit(rule,",",15,&nargs,0);  /* get rule option pairs */

     for( i=0; i<nargs; i++ )
     {
         oargs = mSplit(args[i]," ",2,&noargs,0);  /* get rule option pairs */
         
	 if( noargs != 2 )
         {
             FatalError("Threshold Parse: argument pairing error\n");
         }

         if( strcmp(oargs[0],"type")==0 )
         {
            if( strcmp(oargs[1],"limit") == 0 )
            {
               thdx.type = THD_TYPE_LIMIT;
            }
            else if( strcmp(oargs[1],"threshold") == 0 )
            {
               thdx.type = THD_TYPE_THRESHOLD;
            }
            else if( strcmp(oargs[1],"both") == 0 )
            {
               thdx.type = THD_TYPE_BOTH;
            }
            else
            {
                /* Fatal incorrect threshold type */
                 FatalError("Threshold-Parse: incorrect 'type' argument \n");
            }
            type_flag++;
         }

         else if( strcmp(oargs[0],"track")==0 )
         {
            if( strcmp(oargs[1],"by_src") == 0 )
            {
                thdx.tracking = THD_TRK_SRC;
            }
            else if( strcmp(oargs[1],"by_dst") == 0 )
            {
                thdx.tracking = THD_TRK_DST;
            }
            else
            {
                /* Fatal incorrect threshold type */
                 FatalError("Threshold-Parse: incorrect tracking type\n");
            }
            tracking_flag++;
         }

	 else if( strcmp(oargs[0],"count")==0 )
         {
            thdx.count = xatou(oargs[1],"threshold: count");
            count_flag++;
         }

         else if( strcmp(oargs[0],"seconds")==0 )
         {
            thdx.seconds = xatou(oargs[1],"threshold: seconds");
            seconds_flag++;
         }

         else if( strcmp(oargs[0],"gen_id")==0 )
         {
            thdx.gen_id =  xatou(oargs[1],"threshold: gen_id");
            genid_flag++;

	    if( oargs[1][0]== '-' ) 
                FatalError("Threshold-Parse: gen_id < 0 not supported  '%s %s'\n",oargs[0],oargs[1]);
         }

         else if( strcmp(oargs[0],"sig_id")==0 )
         {
            thdx.sig_id = xatou(oargs[1],"threshold: sig_id");
            sigid_flag++;
	    if( oargs[1][0]== '-' ) 
                FatalError("Threshold-Parse: sig_id < 0 not supported  '%s %s'\n",oargs[0],oargs[1]);
         }
         else
         {
             /* Fatal incorrect threshold type */
             FatalError("Threshold-Parse: unsupported option : %s %s\n",oargs[0],oargs[1]);
         }
     }

     if( (count_flag + tracking_flag + type_flag + seconds_flag + genid_flag + sigid_flag) != 6 )
     {
	/* Fatal - incorrect argument count */
	FatalError("Threshold-Parse: incorrect argument count\n");
     }

     if( sfthreshold_create( &thdx  ) )
     {
	if( thdx.sig_id == 0 )
	{
	   FatalError("Global Threshold-Parse: could not create a threshold object -- only one per gen_id=%u!\n",thdx.gen_id);
	}
	else
	{
	   if( thdx.gen_id ==  0 )
	   {
	      FatalError("Global Threshold-Parse: could not create a threshold object -- a gen_id < 0 requires a sig_id < 0, sig_id=%u !\n",thdx.sig_id);
	   }
	   else
	   {
	      FatalError("Threshold-Parse: could not create a threshold object -- only one per sig_id=%u!\n",thdx.sig_id);
	   }
	}
     }

     mSplitFree(&args, nargs);
     mSplitFree(&oargs, noargs);
}
Esempio n. 25
0
unsigned type FAST_FUNC xatou()(const char *numstr)
{
	return xatou(_sfx)(numstr, NULL);
}
Esempio n. 26
0
int beep_main(int argc, char **argv)
{
	int speaker = get_console_fd_or_die();
	unsigned tickrate_div_freq = tickrate_div_freq; /* for compiler */
	unsigned length = length;
	unsigned delay = delay;
	unsigned rep = rep;
	int c;

	c = 'n';
	while (c != -1) {
		if (c == 'n') {
			tickrate_div_freq = CLOCK_TICK_RATE / FREQ;
			length = LENGTH;
			delay = DELAY;
			rep = REPETITIONS;
		}
		c = getopt(argc, argv, "f:l:d:r:n");
/* TODO: -s, -c:
 * pipe stdin to stdout, but also beep after each line (-s) or char (-c)
 */
		switch (c) {
		case 'f':
/* TODO: what "-f 0" should do? */
			tickrate_div_freq = (unsigned)CLOCK_TICK_RATE / xatou(optarg);
			continue;
		case 'l':
			length = xatou(optarg);
			continue;
		case 'd':
/* TODO:
 * -d N, -D N
 * specify a delay of N milliseconds between repetitions.
 * -d specifies that this delay should only occur between beeps,
 * that is, it should not occur after the last repetition.
 * -D indicates that the delay should occur after every repetition
 */
			delay = xatou(optarg);
			continue;
		case 'r':
			rep = xatou(optarg);
			continue;
		case 'n':
		case -1:
			break;
		default:
			bb_show_usage();
		}
		while (rep) {
//bb_info_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay);
			xioctl(speaker, KIOCSOUND, (void*)(long)tickrate_div_freq);
			usleep(1000 * length);
			ioctl(speaker, KIOCSOUND, (void*)0);
			if (--rep)
				usleep(delay);
		}
	}

	if (ENABLE_FEATURE_CLEAN_UP)
		close(speaker);
	return EXIT_SUCCESS;
}
int split_main(int argc, char **argv)
{
	unsigned suffix_len = 2;
	char *pfx;
	char *count_p;
	const char *sfx;
	off_t cnt = 1000;
	off_t remaining = 0;
	unsigned opt;
	ssize_t bytes_read, to_write;
	char *src;

	opt_complementary = "?2";
	opt = getopt32(argv, "l:b:a:", &count_p, &count_p, &sfx);

	if (opt & SPLIT_OPT_l)
		cnt = xatoul(count_p);
	if (opt & SPLIT_OPT_b)
		cnt = xatoul_sfx(count_p, split_suffices);
	if (opt & SPLIT_OPT_a)
		suffix_len = xatou(sfx);
	sfx = "x";

	argv += optind;
	if (argv[0]) {
		if (argv[1])
			sfx = argv[1];
		xmove_fd(xopen(argv[0], O_RDONLY), 0);
	} else {
		argv[0] = (char *) bb_msg_standard_input;
	}

	if (NAME_MAX < strlen(sfx) + suffix_len)
		bb_error_msg_and_die("suffix too long");

	{
		char *char_p = xzalloc(suffix_len + 1);
		memset(char_p, 'a', suffix_len);
		pfx = xasprintf("%s%s", sfx, char_p);
		if (ENABLE_FEATURE_CLEAN_UP)
			free(char_p);
	}

	while (1) {
		bytes_read = safe_read(0, read_buffer, READ_BUFFER_SIZE);
		if (!bytes_read)
			break;
		if (bytes_read < 0)
			bb_simple_perror_msg_and_die(argv[0]);
		src = read_buffer;
		do {
			if (!remaining) {
				if (!pfx)
					bb_error_msg_and_die("suffixes exhausted");
				xmove_fd(xopen(pfx, O_WRONLY | O_CREAT | O_TRUNC), 1);
				pfx = next_file(pfx, suffix_len);
				remaining = cnt;
			}

			if (opt & SPLIT_OPT_b) {
				/* split by bytes */
				to_write = (bytes_read < remaining) ? bytes_read : remaining;
				remaining -= to_write;
			} else {
				/* split by lines */
				/* can be sped up by using _memrchr_
				 * and writing many lines at once... */
				char *end = memchr(src, '\n', bytes_read);
				if (end) {
					--remaining;
					to_write = end - src + 1;
				} else {
					to_write = bytes_read;
				}
			}

			xwrite(1, src, to_write);
			bytes_read -= to_write;
			src += to_write;
		} while (bytes_read);
	}
	return EXIT_SUCCESS;
}
Esempio n. 28
0
int tail_main(int argc, char **argv)
{
	unsigned count = 10;
	unsigned sleep_period = 1;
	bool from_top;
	int header_threshhold = 1;
	const char *str_c, *str_n, *str_s;

	char *tailbuf;
	size_t tailbufsize;
	int taillen = 0;
	int newline = 0;
	int nfiles, nread, nwrite, seen, i, opt;

	int *fds;
	char *s, *buf;
	const char *fmt;

#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL
	/* Allow legacy syntax of an initial numeric option without -n. */
	if (argc >= 2 && (argv[1][0] == '+' || argv[1][0] == '-')
	 && isdigit(argv[1][1])
	) {
		argv[0] = (char*)"-n";
		argv--;
		argc++;
	}
#endif

	opt = getopt32(argc, argv, "fc:n:" USE_FEATURE_FANCY_TAIL("qs:v"), &str_c, &str_n, &str_s);
#define FOLLOW (opt & 0x1)
#define COUNT_BYTES (opt & 0x2)
	//if (opt & 0x1) // -f
	if (opt & 0x2) count = eat_num(str_c); // -c
	if (opt & 0x4) count = eat_num(str_n); // -n
#if ENABLE_FEATURE_FANCY_TAIL
	if (opt & 0x8) header_threshhold = INT_MAX; // -q
	if (opt & 0x10) sleep_period = xatou(str_s); // -s
	if (opt & 0x20) header_threshhold = 0; // -v
#endif
	argc -= optind;
	argv += optind;
	from_top = status;

	/* open all the files */
	fds = xmalloc(sizeof(int) * (argc + 1));
	status = nfiles = i = 0;
	if (argc == 0) {
		struct stat statbuf;

		if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) {
			opt &= ~1; /* clear FOLLOW */
		}
		*argv = (char *) bb_msg_standard_input;
		goto DO_STDIN;
	}

	do {
		if (NOT_LONE_DASH(argv[i])) {
			fds[nfiles] = open(argv[i], O_RDONLY);
			if (fds[nfiles] < 0) {
				bb_perror_msg("%s", argv[i]);
				status = EXIT_FAILURE;
				continue;
			}
		} else {
 DO_STDIN:		/* "-" */
			fds[nfiles] = STDIN_FILENO;
		}
		argv[nfiles] = argv[i];
		++nfiles;
	} while (++i < argc);

	if (!nfiles)
		bb_error_msg_and_die("no files");

	tailbufsize = BUFSIZ;

	/* tail the files */
	if (!from_top && COUNT_BYTES) {
		if (tailbufsize < count) {
			tailbufsize = count + BUFSIZ;
		}
	}

	buf = tailbuf = xmalloc(tailbufsize);

	fmt = header_fmt + 1;	/* Skip header leading newline on first output. */
	i = 0;
	do {
		/* Be careful.  It would be possible to optimize the count-bytes
		 * case if the file is seekable.  If you do though, remember that
		 * starting file position may not be the beginning of the file.
		 * Beware of backing up too far.  See example in wc.c.
		 */
		if (!(count | from_top) && lseek(fds[i], 0, SEEK_END) >= 0) {
			continue;
		}

		if (nfiles > header_threshhold) {
			tail_xprint_header(fmt, argv[i]);
			fmt = header_fmt;
		}

		buf = tailbuf;
		taillen = 0;
		seen = 1;
		newline = 0;

		while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
			if (from_top) {
				nwrite = nread;
				if (seen < count) {
					if (COUNT_BYTES) {
						nwrite -= (count - seen);
						seen = count;
					} else {
						s = buf;
						do {
							--nwrite;
							if (*s++ == '\n' && ++seen == count) {
								break;
							}
						} while (nwrite);
					}
				}
				xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite);
			} else if (count) {
				if (COUNT_BYTES) {
					taillen += nread;
					if (taillen > count) {
						memmove(tailbuf, tailbuf + taillen - count, count);
						taillen = count;
					}
				} else {
					int k = nread;
					int nbuf = 0;

					while (k) {
						--k;
						if (buf[k] == '\n') {
							++nbuf;
						}
					}

					if (newline + nbuf < count) {
						newline += nbuf;
						taillen += nread;

					} else {
						int extra = 0;
						if (buf[nread-1] != '\n') {
							extra = 1;
						}

						k = newline + nbuf + extra - count;
						s = tailbuf;
						while (k) {
							if (*s == '\n') {
								--k;
							}
							++s;
						}

						taillen += nread - (s - tailbuf);
						memmove(tailbuf, s, taillen);
						newline = count - extra;
					}
					if (tailbufsize < taillen + BUFSIZ) {
						tailbufsize = taillen + BUFSIZ;
						tailbuf = xrealloc(tailbuf, tailbufsize);
					}
				}
				buf = tailbuf + taillen;
			}
		}

		if (!from_top) {
			xwrite(STDOUT_FILENO, tailbuf, taillen);
		}

		taillen = 0;
	} while (++i < nfiles);

	buf = xrealloc(tailbuf, BUFSIZ);

	fmt = NULL;

	if (FOLLOW) while (1) {
		sleep(sleep_period);
		i = 0;
		do {
			if (nfiles > header_threshhold) {
				fmt = header_fmt;
			}
			while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) {
				if (fmt) {
					tail_xprint_header(fmt, argv[i]);
					fmt = NULL;
				}
				xwrite(STDOUT_FILENO, buf, nread);
			}
		} while (++i < nfiles);
	}

	return status;
}