Example #1
0
 static int_adapter from_special(special_values sv)
 {
   switch (sv) {
   case not_a_date_time: return not_a_number();
   case neg_infin:       return neg_infinity();
   case pos_infin:       return pos_infinity();
   case max_date_time:   return (max)();
   case min_date_time:   return (min)();
   default:              return not_a_number();
   }
 }
Example #2
0
/*
 * Initialize 'constants' stored as variables (user could mangle these)
 */
void
init_constants()
{
    (void) Gcomplex(&udv_pi.udv_value, M_PI, 0.0);
    udv_NaN = get_udv_by_name("NaN");
    (void) Gcomplex(&(udv_NaN->udv_value), not_a_number(), 0.0);
}
Example #3
0
void
f_value(union argument *arg)
{
    struct udvt_entry *p = first_udv;
    struct value a;
    struct value result;

    (void) arg;
    (void) pop(&a);

    if (a.type != STRING) {
	/* int_warn(NO_CARET,"non-string value passed to value()"); */
	push(&a);
	return;
    }

    while (p) {
	if (!strcmp(p->udv_name, a.v.string_val)) {
	    result = p->udv_value;
	    if (p->udv_undef)
		p = NULL;
	    else if (result.type == STRING)
		result.v.string_val = gp_strdup(result.v.string_val);
	    break;
	}
	p = p->next_udv;
    }
    gpfree_string(&a);
    if (!p) {
	/* int_warn(NO_CARET,"undefined variable name passed to value()"); */
	result.type = CMPLX;
	result.v.cmplx_val.real = not_a_number();
    }
    push(&result);
}
Example #4
0
 int_adapter operator-(int_type rhs) const
 {
   if (is_nan()) {
     return int_adapter<int_type>(not_a_number());
   }
   if (is_infinity()) {
     return *this;
   }
   return int_adapter<int_type>(value_ - rhs);
 }
Example #5
0
 int_adapter operator-(const int_adapter& rhs) const
 {
   if (is_nan() || rhs.is_nan()) {
     return int_adapter<int_type>(not_a_number());
   }
   if (is_infinity()) {
     return *this;
   }
   if (rhs.is_infinity()) {
     return rhs;
   }
   return int_adapter<int_type>(value_ - rhs.value_);
 }
Example #6
0
 //! Assumes 'this' is a special value
 int_adapter mult_div_specials(const int& rhs) const
 {
   int min_value; 
   // quiets compiler warnings
   bool is_signed = std::numeric_limits<int_type>::is_signed;
   if(is_signed) {
     min_value = 0;
   }
   else {
     min_value = 1;// there is no zero with unsigned
   }
   if(this->is_nan()) {
     return int_adapter<int_type>(not_a_number());
   }
   if((*this > 0 && rhs > 0) || (*this < min_value && rhs < 0)) {
       return int_adapter<int_type>(pos_infinity());
   }
   if((*this > 0 && rhs < 0) || (*this < min_value && rhs > 0)) {
       return int_adapter<int_type>(neg_infinity());
   }
   //implied -> if(this->value_ == 0 || rhs.value_ == 0)
   return int_adapter<int_type>(not_a_number());
 }
Example #7
0
 int_adapter operator+(const int_type rhs) const
 {
   if(is_special())
   {
     if (is_nan()) 
     {
       return int_adapter<int_type>(not_a_number());
     }
     if (is_infinity()) 
     {
       return *this;
     }
   }
   return int_adapter<int_type>(value_ + rhs);
 }
Example #8
0
/* 0 == ERROR here! */
double get_labeled_arg(int fd, char *label, char **nextargs) {
	char *arg = strtok_r(NULL, " ", nextargs);
	if (!arg) {
		printoutc(fd, "missing parameter '%s'", label);
		return 0.0; //error
	}
	if (!match_input(label, arg)) {
		printoutc(fd, "invalid parameter \"%s\", expecting \"%s\"", arg, label);
		return 0.0; //error
	}
	arg = strtok_r(NULL, " ", nextargs);
	if (not_a_number(arg) && arg[0] != '.') {
		printoutc(fd, "invalid value \"%s\"", arg);
		return 0.0; //error
	}
	return strtod(arg, NULL);
}
Example #9
0
 // should templatize this to be consistant with op +-
 int_adapter operator%(const int_adapter& rhs)const
 {
   if(this->is_special() || rhs.is_special())
   {
     if(is_infinity() && rhs.is_infinity())
     {
       return int_adapter<int_type>(not_a_number());
     }
     if(rhs != 0)
     {
       return mult_div_specials(rhs);
     }
     else { // let divide by zero blow itself up
       return int_adapter<int_type>(value_ % rhs.value_);
     }
   }
   return int_adapter<int_type>(value_ % rhs.value_);
 }
Example #10
0
static struct vder_iface *select_interface(char *arg)
{
	struct vder_iface *iface, *selected = NULL;;
	int iface_id;


	if (strncmp(arg,"eth",3)) {
		return NULL;
	}

	if (not_a_number(arg + 3))
		return NULL;

	iface_id = strtol(arg + 3, NULL, 10);
	iface = Router.iflist;
	while(iface) {
		if (iface_id == iface->interface_id) {
			selected = iface;
			break;
		}
		iface = iface->next;
	}
	return selected;
}
Example #11
0
int
main(int argc, char **argv)
#endif
{
    int i;

#ifdef LINUXVGA
    LINUX_setup();		/* setup VGA before dropping privilege DBT 4/5/99 */
    drop_privilege();
#endif
/* make sure that we really have revoked root access, this might happen if
   gnuplot is compiled without vga support but is installed suid by mistake */
#ifdef __linux__
    setuid(getuid());
#endif

#if defined(MSDOS) && !defined(_Windows) && !defined(__GNUC__)
    PC_setup();
#endif /* MSDOS !Windows */

/* HBB: Seems this isn't needed any more for DJGPP V2? */
/* HBB: disable all floating point exceptions, just keep running... */
#if defined(DJGPP) && (DJGPP!=2)
    _control87(MCW_EM, MCW_EM);
#endif

#if defined(OS2)
    int rc;
#ifdef OS2_IPC
    char semInputReadyName[40];
    sprintf( semInputReadyName, "\\SEM32\\GP%i_Input_Ready", getpid() );
    rc = DosCreateEventSem(semInputReadyName,&semInputReady,0,0);
    if (rc != 0)
      fputs("DosCreateEventSem error\n",stderr);
#endif
    rc = RexxRegisterSubcomExe("GNUPLOT", (PFN) RexxInterface, NULL);
#endif

/* malloc large blocks, otherwise problems with fragmented mem */
#ifdef MALLOCDEBUG
    malloc_debug(7);
#endif

/* get helpfile from home directory */
#ifdef __DJGPP__
    {
	char *s;
	strcpy(HelpFile, argv[0]);
	for (s = HelpFile; *s; s++)
	    if (*s == DIRSEP1)
		*s = DIRSEP2;	/* '\\' to '/' */
	strcpy(strrchr(HelpFile, DIRSEP2), "/gnuplot.gih");
    }			/* Add also some "paranoid" tests for '\\':  AP */
#endif /* DJGPP */

#ifdef VMS
    unsigned int status[2] = { 1, 0 };
#endif

#if defined(HAVE_LIBEDITLINE)
    rl_getc_function = getc_wrapper;
#endif

#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE)
    /* T.Walter 1999-06-24: 'rl_readline_name' must be this fix name.
     * It is used to parse a 'gnuplot' specific section in '~/.inputrc' 
     * or gnuplot specific commands in '.editrc' (when using editline
     * instead of readline) */
    rl_readline_name = "Gnuplot";
    rl_terminal_name = getenv("TERM");
    using_history();
#endif
#if defined(HAVE_LIBREADLINE) && !defined(MISSING_RL_TILDE_EXPANSION)
    rl_complete_with_tilde_expansion = 1;
#endif

    for (i = 1; i < argc; i++) {
	if (!argv[i])
	    continue;

	if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) {
	    printf("gnuplot %s patchlevel %s\n",
		    gnuplot_version, gnuplot_patchlevel);
	    return 0;

	} else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
	    printf( "Usage: gnuplot [OPTION]... [FILE]\n"
#ifdef X11
		    "for X11 options see 'help X11->command-line-options'\n"
#endif
		    "  -V, --version\n"
		    "  -h, --help\n"
		    "  -p  --persist\n"
		    "  -e  \"command1; command2; ...\"\n"
		    "gnuplot %s patchlevel %s\n"
#ifdef DIST_CONTACT
		    "Report bugs to "DIST_CONTACT"\n"
		    "            or %s\n",
#else
		    "Report bugs to %s\n",
#endif
		    gnuplot_version, gnuplot_patchlevel, bug_email);
	    return 0;

	} else if (!strncmp(argv[i], "-persist", 2) || !strcmp(argv[i], "--persist")) {
	    persist_cl = TRUE;
	}
    }

#ifdef X11
    /* the X11 terminal removes tokens that it recognizes from argv. */
    {
	int n = X11_args(argc, argv);
	argv += n;
	argc -= n;
    }
#endif

    setbuf(stderr, (char *) NULL);

#ifdef HAVE_SETVBUF
    /* this was once setlinebuf(). Docs say this is
     * identical to setvbuf(,NULL,_IOLBF,0), but MS C
     * faults this (size out of range), so we try with
     * size of 1024 instead. [SAS/C does that, too. -lh]
     * Failing this, I propose we just make the call and
     * ignore the return : its probably not a big deal
     */
    if (setvbuf(stdout, (char *) NULL, _IOLBF, (size_t) 1024) != 0)
	(void) fputs("Could not linebuffer stdout\n", stderr);

#ifdef X11
    /* This call used to be in x11.trm, with the following comment:
     *   Multi-character inputs like escape sequences but also mouse-pasted
     *   text got buffered and therefore didn't trigger the select() function
     *   in X11_waitforinput(). Switching to unbuffered input solved this.
     *   23 Jan 2002 (joze)
     * But switching to unbuffered mode causes all characters in the input
     * buffer to be lost. So the only safe time to do it is on program entry.
     * The #ifdef X11 is probably unnecessary, but makes the change minimal.
     * Do any non-X platforms suffer from the same problem?
     * EAM - Jan 2004.
     */
    setvbuf(stdin, (char *) NULL, _IONBF, 0);
#endif

#endif

    gpoutfile = stdout;

    /* Initialize pre-loaded user variables */
    (void) Gcomplex(&udv_pi.udv_value, M_PI, 0.0);
    udv_NaN = add_udv_by_name("NaN");
    (void) Gcomplex(&(udv_NaN->udv_value), not_a_number(), 0.0);
    udv_NaN->udv_undef = FALSE;

    init_memory();

    interactive = FALSE;
    init_terminal();		/* can set term type if it likes */
    push_terminal(0);		/* remember the default terminal */

    /* reset the terminal when exiting */
    /* this is done through gp_atexit so that other terminal functions
     * can be registered to be executed before the terminal is reset. */
    GP_ATEXIT(term_reset);

# if defined(_Windows) && ! defined(WGP_CONSOLE)
    interactive = TRUE;
# else
    interactive = isatty(fileno(stdin));
# endif

    if (argc > 1)
	interactive = noinputfiles = FALSE;
    else
	noinputfiles = TRUE;

    /* Need this before show_version is called for the first time */

#ifdef HAVE_SYS_UTSNAME_H
    {
	struct utsname uts;

	/* something is fundamentally wrong if this fails ... */
	if (uname(&uts) > -1) {
# ifdef _AIX
	    strcpy(os_name, uts.sysname);
	    sprintf(os_name, "%s.%s", uts.version, uts.release);
# elif defined(SCO)
	    strcpy(os_name, "SCO");
	    strcpy(os_rel, uts.release);
# elif defined(DJGPP)
	    if (!strncmp(uts.sysname, "??Un", 4)) /* don't print ??Unknow" */
		strcpy(os_name, "Unknown");
	    else {
		strcpy(os_name, uts.sysname);
		strcpy(os_rel, uts.release);
	    }
# else
	    strcpy(os_name, uts.sysname);
	    strcpy(os_rel, uts.release);
# ifdef OS2
	    if (!strchr(os_rel,'.'))
		/* write either "2.40" or "4.0", or empty -- don't print "OS/2 1" */
		strcpy(os_rel, "");
# endif

# endif
	}
    }
#else /* ! HAVE_SYS_UTSNAME_H */

    strcpy(os_name, OS);
    strcpy(os_rel, "");

#endif /* HAVE_SYS_UTSNAME_H */

    if (interactive)
	show_version(stderr);
    else
	show_version(NULL); /* Only load GPVAL_COMPILE_OPTIONS */

#ifdef WGP_CONSOLE
#ifdef CONSOLE_SWITCH_CP
    if (cp_changed && interactive) {
	fprintf(stderr,
	    "\ngnuplot changed the codepage of this console from %i to %i to\n" \
	    "match the graph window. Some characters might only display correctly\n" \
	    "if you change the font to a non-raster type.\n", 
	    cp_input, GetConsoleCP());
    }
#else
    if ((GetConsoleCP() != GetACP()) && interactive) {
	fprintf(stderr,
	    "\nWarning: The codepage of the graph window (%i) and that of the\n" \
	    "console (%i) differ. Use `set encoding` or `!chcp` if extended\n" \
	    "characters don't display correctly.\n", 
	    GetACP(), GetConsoleCP());
    }
#endif
#endif

    update_gpval_variables(3);  /* update GPVAL_ variables available to user */

#ifdef VMS
    /* initialise screen management routines for command recall */
    if (status[1] = smg$create_virtual_keyboard(&vms_vkid) != SS$_NORMAL)
	done(status[1]);
    if (status[1] = smg$create_key_table(&vms_ktid) != SS$_NORMAL)
	done(status[1]);
#endif /* VMS */

    if (!SETJMP(command_line_env, 1)) {
	/* first time */
	interrupt_setup();
	/* should move this stuff another initialisation routine,
	 * something like init_set() maybe */
	get_user_env();
	init_loadpath();
	init_locale();
	/* HBB: make sure all variables start in the same mode 'reset'
	 * would set them to. Since the axis variables aren't in
	 * initialized arrays any more, this is now necessary... */
	reset_command();
	init_color();  /*  Initialization of color  */
	load_rcfile();
	init_fit();		/* Initialization of fitting module */

	if (interactive && term != 0) {		/* not unknown */
#ifdef GNUPLOT_HISTORY
	    FPRINTF((stderr, "Before read_history\n"));
#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE)
	    expanded_history_filename = tilde_expand(GNUPLOT_HISTORY_FILE);
#else
	    expanded_history_filename = gp_strdup(GNUPLOT_HISTORY_FILE);
	    gp_expand_tilde(&expanded_history_filename);
#endif
	    FPRINTF((stderr, "expanded_history_filename = %s\n", expanded_history_filename));
	    read_history(expanded_history_filename);
	    {
		/* BEGIN: Go local to get environment variable */
		const char *temp_env = getenv ("GNUPLOT_HISTORY_SIZE");
		if (temp_env)
		    gnuplot_history_size = strtol (temp_env, (char **) NULL, 10);
	    } /* END: Go local to get environment variable */

	    /*
	     * It is safe to ignore the return values of 'atexit()' and
	     * 'on_exit()'. In the worst case, there is no history of your
	     * currrent session and you have to type all again in your next
	     * session.
	     * This is the default behaviour (traditional reasons), too.
	     * In case you don't have one of these functions, or you don't
	     * want to use them, 'write_history()' is called directly.
	     */
	    GP_ATEXIT(wrapper_for_write_history);
#endif /* GNUPLOT_HISTORY */

	    fprintf(stderr, "\nTerminal type set to '%s'\n", term->name);
	}			/* if (interactive && term != 0) */
    } else {
	/* come back here from int_error() */
	if (interactive == FALSE)
	    exit_status = EXIT_FAILURE;
#ifdef HAVE_READLINE_RESET
	else
	{
	    /* reset properly readline after a SIGINT+longjmp */
	    rl_reset_after_signal ();
	}
#endif

	load_file_error();	/* if we were in load_file(), cleanup */
	SET_CURSOR_ARROW;

#ifdef VMS
	/* after catching interrupt */
	/* VAX stuffs up stdout on SIGINT while writing to stdout,
	   so reopen stdout. */
	if (gpoutfile == stdout) {
	    if ((stdout = freopen("SYS$OUTPUT", "w", stdout)) == NULL) {
		/* couldn't reopen it so try opening it instead */
		if ((stdout = fopen("SYS$OUTPUT", "w")) == NULL) {
		    /* don't use int_error here - causes infinite loop! */
		    fputs("Error opening SYS$OUTPUT as stdout\n", stderr);
		}
	    }
	    gpoutfile = stdout;
	}
#endif /* VMS */
	if (!interactive && !noinputfiles) {
	    term_reset();
	    exit(EXIT_FAILURE);	/* exit on non-interactive error */
	}
    }

    if (argc > 1) {
#ifdef _Windows
	TBOOLEAN noend = persist_cl;
#endif

	/* load filenames given as arguments */
	while (--argc > 0) {
	    ++argv;
	    c_token = 0;
#ifdef _Windows
	    if (stricmp(*argv, "-noend") == 0 || stricmp(*argv, "/noend") == 0
	       	|| stricmp(*argv, "-persist") == 0)
		noend = TRUE;
	    else
#endif
	    if (!strncmp(*argv, "-persist", 2) || !strcmp(*argv, "--persist")) {
		FPRINTF((stderr,"'persist' command line option recognized\n"));

	    } else if (strcmp(*argv, "-") == 0) {
		interactive = TRUE;
		while (!com_line());
		interactive = FALSE;

	    } else if (strcmp(*argv, "-e") == 0) {
		--argc; ++argv;
		if (argc <= 0) {
		    fprintf(stderr, "syntax:  gnuplot -e \"commands\"\n");
		    return 0;
		}
		do_string(*argv);

	    } else {
		load_file(loadpath_fopen(*argv, "r"), gp_strdup(*argv), FALSE);
	    }
	}
#ifdef _Windows
	if (noend) {
	    interactive = TRUE;
	    while (!com_line());
	}
#endif
    } else {
	/* take commands from stdin */
	while (!com_line());
    }

#if (defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE)) && defined(GNUPLOT_HISTORY)
#if !defined(HAVE_ATEXIT) && !defined(HAVE_ON_EXIT)
    /* You should be here if you neither have 'atexit()' nor 'on_exit()' */
    wrapper_for_write_history();
#endif /* !HAVE_ATEXIT && !HAVE_ON_EXIT */
#endif /* (HAVE_LIBREADLINE || HAVE_LIBEDITLINE) && GNUPLOT_HISTORY */

#ifdef OS2
    RexxDeregisterSubcom("GNUPLOT", NULL);
#endif

    /* HBB 20040223: Not all compilers like exit() to end main() */
    /* exit(exit_status); */
    return exit_status;
}
Example #12
0
 static bool is_not_a_number(int_type v)
 {
   return (v == not_a_number().as_number());
 }
Example #13
0
 bool is_nan() const
 {
   return (value_ == not_a_number().as_number());
 }
Example #14
0
static int queue(int fd, char *s)
{
	struct vder_iface *cur = Router.iflist, *selected = NULL;
	struct vder_queue *q;
	char *nextargs, *arg;
	int if_id;
	int prio_id = -1;
	char output_word[MAXCMD] = "";
	enum queue_policy_e newpolicy;

	arg = strtok_r(s, " ", &nextargs);
	if(!arg) {
		/* No arguments */
		while(cur) {
			show_queues(fd, cur);
			cur = cur->next;
		}
		return 0;
	}
	if ((sscanf(arg, "eth%d:prio%d", &if_id, &prio_id) != 2) && (sscanf(arg, "eth%d:%s", &if_id, output_word) != 2))
		return EINVAL;
	else {
		if (prio_id < 0 && !match_input("output", output_word)) {
			return EINVAL;
		}
		cur = Router.iflist;
		while(cur) {
			if (cur->interface_id == if_id) {
				selected = cur;
				break;
			}
			cur = cur->next;
		}

		if (!selected) {
			printoutc(fd, "Cannot find interface eth%d", if_id);
			return ENOENT;
		}

		/* Match policy */
		arg = strtok_r(NULL, " ", &nextargs);
		if (!arg) {
			printoutc(fd, "queue: queue policy required");
			return EINVAL;
		}
		if (match_input("unlimited", arg)) {
			newpolicy = QPOLICY_UNLIMITED;
		} else if (match_input("fifo", arg)) {
			newpolicy = QPOLICY_FIFO;
		} else if (match_input("red", arg)) {
			newpolicy = QPOLICY_RED;
		} else if (match_input("token", arg)) {
			newpolicy = QPOLICY_TOKEN;
		} else {
			printoutc(fd, "queue: invalid queue policy \"%s\"", arg);
			return EINVAL;
		}
		if (prio_id >= 0) {
			if (prio_id > 31) {
				printoutc(fd, "Invalid priority queue %s", arg);
				return EINVAL;
			}
			q = &selected->prio_q[prio_id];
		} else {
			printoutc(fd, "selected if=%d, outq", if_id);
			q = &selected->out_q;
		}

		/* Match arguments */
		if (newpolicy == QPOLICY_UNLIMITED) {
			qunlimited_setup(q);
		} else if (newpolicy == QPOLICY_FIFO) {
			uint32_t limit;
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg) {
				printoutc(fd, "fifo: missing parameter 'limit'");
				return EINVAL;
			}
			if (!match_input("limit", arg)) {
				printoutc(fd, "fifo: invalid parameter \"%s\"", arg);
				return EINVAL;
			}
			arg = strtok_r(NULL, " ", &nextargs);
			if (not_a_number(arg)) {
				printoutc(fd, "fifo: invalid limit");
				return EINVAL;
			}
			limit = strtol(arg, NULL, 10);
			qfifo_setup(q,limit);

		} else if (newpolicy == QPOLICY_RED) {
			uint32_t min, max, limit;
			double P;
			min = (uint32_t) get_labeled_arg(fd,"min", &nextargs);
			max = (uint32_t) get_labeled_arg(fd,"max", &nextargs);
			P = get_labeled_arg(fd,"probability", &nextargs);
			limit = (uint32_t) get_labeled_arg(fd,"limit", &nextargs);
			if (!min || !max || !limit)
				return EINVAL;
			qred_setup(q, min, max, P, limit);
		} else if (newpolicy == QPOLICY_TOKEN) {
			uint32_t limit, bitrate;
			limit = (uint32_t) get_labeled_arg(fd, "limit", &nextargs);
			bitrate = (uint32_t) get_labeled_arg(fd, "bitrate", &nextargs);
			if (!limit || !bitrate)
				return EINVAL;
			qtoken_setup(q, bitrate, limit);
		}
		return 0;
	}
}
Example #15
0
static int filter(int fd,char *s)
{
	struct vder_filter *cur = Router.filtering_table;
	int action;
	struct vder_iface *vif = NULL;
	uint8_t proto = 0;
	struct in_addr s_addr = {0}, s_nm = {0}, d_addr = {0}, d_nm = {0};
	uint16_t sport = 0, dport = 0;
	int tos = -1;
	uint8_t priority = PRIO_BESTEFFORT;
	enum filter_action filter_action = filter_invalid;
	char *nextargs = NULL, *arg;

	arg = strtok_r(s, " ", &nextargs);
	if(!arg) {
		/* No arguments */
		while(cur) {
			show_filter(fd, cur);
			cur = cur->next;
		}
		return 0;
	}

	if ((!arg) || (strlen(arg) != 3) || ((strncmp(arg, "add", 3) != 0) && (strncmp(arg, "del", 3) != 0))) {
		printoutc(fd, "Invalid action \"%s\".", arg);
		return EINVAL;
	}
	if (strncmp(arg, "del", 3) == 0)
		action = ACTION_DELETE;
	else
		action = ACTION_ADD;

	arg = strtok_r(NULL, " ", &nextargs);
	if (!arg) {
		not_understood(fd, "");
		return EINVAL;
	}

	while(arg) {
		if (match_input("src", arg)) {
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg)
				return EINVAL;
			vif = select_interface(arg);
		} else if(match_input("proto", arg)) {
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg)
				return EINVAL;
			if (not_a_number(arg)) {
				if (match_input("tcp", arg))
					proto = IPPROTO_TCP;
				else if (match_input("udp", arg)) 
					proto = IPPROTO_UDP;
				else if (match_input("igmp", arg))
					proto = IPPROTO_IGMP;
				else if (match_input("icmp", arg))
					proto = IPPROTO_ICMP;
				else {
					printoutc(fd, "Invalid protocol \"%s\"", arg);
					return EINVAL;
				}
			} else {
				proto = atoi(arg);
				if (proto <= 0) {
					printoutc(fd, "Invalid protocol \"%s\"", arg);
					return EINVAL;
				}
			}
		} else if (match_input("from",arg)) {
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg)
				return EINVAL;
			if (!inet_aton(arg, &s_addr) || !is_unicast(s_addr.s_addr)) {
				printoutc(fd, "Invalid from address \"%s\"", arg);
				return EINVAL;
			}
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg) {
				printoutc(fd, "from address: netmask is required");
				return EINVAL;
			}
			if (!inet_aton(arg, &s_nm) || !is_netmask(s_nm.s_addr)) {
				printoutc(fd, "Invalid netmask \"%s\"", arg);
				return EINVAL;
			}
		} else if (match_input("to",arg)) {
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg)
				return EINVAL;
			if (!inet_aton(arg, &d_addr) || !is_unicast(d_addr.s_addr)) {
				printoutc(fd, "Invalid from address \"%s\"", arg);
				return EINVAL;
			}
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg) {
				printoutc(fd, "from address: netmask is required");
				return EINVAL;
			}
			if (!inet_aton(arg, &d_nm) || !is_netmask(d_nm.s_addr)) {
				printoutc(fd, "Invalid netmask \"%s\"", arg);
				return EINVAL;
			}
		} else if (match_input("tos",arg)) {
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg)
				return EINVAL;
			tos = atoi(arg);
			if ((tos < 0) || not_a_number(arg)) {
				printoutc(fd, "Invalid tos %s", arg);
				return EINVAL;
			}
		} else if (match_input("sport",arg)) {
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg)
				return EINVAL;
			if ((sport < 0) || not_a_number(arg)) {
				printoutc(fd, "Invalid sport %s", arg);
				return EINVAL;
			}
			sport = htons(atoi(arg));
		} else if (match_input("dport",arg)) {
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg)
				return EINVAL;
			if (not_a_number(arg)) {
				printoutc(fd, "Invalid dport %s", arg);
				return EINVAL;
			}
			dport = htons(atoi(arg));
		} else if (match_input("prio",arg)) {
			if (filter_action != filter_invalid) {
				printoutc(fd, "Invalid double action for filter");
			}
			arg = strtok_r(NULL, " ", &nextargs);
			if (!arg)
				return EINVAL;
			priority = atoi(arg);
			if ((priority < 0) || (priority >= PRIO_NUM) || not_a_number(arg)) {
				printoutc(fd, "Invalid priority %s", arg);
				return EINVAL;
			}
			filter_action = filter_priority;
		} else if (match_input("accept",arg)) {
			if (filter_action != filter_invalid) {
				printoutc(fd, "Invalid double action for filter");
			}
			filter_action = filter_accept;
		} else if (match_input("reject",arg)) {
			if (filter_action != filter_invalid) {
				printoutc(fd, "Invalid double action for filter");
			}
			filter_action = filter_reject;
		} else if (match_input("drop",arg)) {
			if (filter_action != filter_invalid) {
				printoutc(fd, "Invalid double action for filter");
			}
			filter_action = filter_drop;
		}
		arg = strtok_r(NULL, " ", &nextargs);
	}
	if ((filter_action == filter_invalid) && (action == ACTION_ADD)) {
		printoutc(fd, "Error: an action is required for filter");
		return EINVAL;
	}
	if (action == ACTION_ADD) {
		if (vder_filter_add(vif, proto, s_addr.s_addr, s_nm.s_addr, d_addr.s_addr, d_nm.s_addr, tos, sport, dport, filter_action, priority))
			return errno;
	} else {
		if (vder_filter_del(vif, proto, s_addr.s_addr, s_nm.s_addr, d_addr.s_addr, d_nm.s_addr, tos, sport, dport))
			return errno;
	}
	return 0;
}