Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Feb 2010 16:17:38 +0000 (UTC)
From:      Luigi Rizzo <luigi@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r204209 - user/luigi/ipfw3-head/sbin/ipfw
Message-ID:  <201002221617.o1MGHcYl094335@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: luigi
Date: Mon Feb 22 16:17:37 2010
New Revision: 204209
URL: http://svn.freebsd.org/changeset/base/204209

Log:
  simplify the command parsing by creating a n av[] array with a NULL
  entry at the end. This removes the need to carry both ac and av
  during the processing of the arguments.
  (not all routines are converted).
  
  Submitted by:	Marta Carbone

Modified:
  user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c
  user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
  user/luigi/ipfw3-head/sbin/ipfw/main.c

Modified: user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c	Mon Feb 22 16:16:16 2010	(r204208)
+++ user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c	Mon Feb 22 16:17:37 2010	(r204209)
@@ -57,7 +57,7 @@ struct cmdline_opts co;	/* global option
 int resvd_set_number = RESVD_SET;
 
 #define GET_UINT_ARG(arg, min, max, tok, s_x) do {			\
-	if (!ac)							\
+	if (!av[0])							\
 		errx(EX_USAGE, "%s: missing argument", match_value(s_x, tok)); \
 	if (_substrcmp(*av, "tablearg") == 0) {				\
 		arg = IP_FW_TABLEARG;					\
@@ -1613,17 +1613,16 @@ show_dyn_ipfw(ipfw_dyn_rule *d, int pcwi
  * 	ipfw set move rule X to Y
  */
 void
-ipfw_sets_handler(int ac, char *av[])
+ipfw_sets_handler(char *av[])
 {
 	uint32_t set_disable, masks[2];
 	int i, nbytes;
 	uint16_t rulenum;
 	uint8_t cmd, new_set;
 
-	ac--;
 	av++;
 
-	if (!ac)
+	if (av[0] == NULL)
 		errx(EX_USAGE, "set needs command");
 	if (_substrcmp(*av, "show") == 0) {
 		void *data;
@@ -1649,8 +1648,8 @@ ipfw_sets_handler(int ac, char *av[])
 			}
 		printf("\n");
 	} else if (_substrcmp(*av, "swap") == 0) {
-		ac--; av++;
-		if (ac != 2)
+		av++;
+		if ( av[0] == NULL || av[1] == NULL )
 			errx(EX_USAGE, "set swap needs 2 set numbers\n");
 		rulenum = atoi(av[0]);
 		new_set = atoi(av[1]);
@@ -1661,13 +1660,14 @@ ipfw_sets_handler(int ac, char *av[])
 		masks[0] = (4 << 24) | (new_set << 16) | (rulenum);
 		i = do_cmd(IP_FW_DEL, masks, sizeof(uint32_t));
 	} else if (_substrcmp(*av, "move") == 0) {
-		ac--; av++;
-		if (ac && _substrcmp(*av, "rule") == 0) {
+		av++;
+		if (!av[0] && _substrcmp(*av, "rule") == 0) {
 			cmd = 2;
-			ac--; av++;
+			av++;
 		} else
 			cmd = 3;
-		if (ac != 3 || _substrcmp(av[1], "to") != 0)
+		if (av[0] == NULL || av[1] == NULL || av[2] == NULL ||
+				av[3] != NULL ||  _substrcmp(av[1], "to") != 0)
 			errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
 		rulenum = atoi(av[0]);
 		new_set = atoi(av[2]);
@@ -1682,10 +1682,10 @@ ipfw_sets_handler(int ac, char *av[])
 		   _substrcmp(*av, "enable") == 0 ) {
 		int which = _substrcmp(*av, "enable") == 0 ? 1 : 0;
 
-		ac--; av++;
+		av++;
 		masks[0] = masks[1] = 0;
 
-		while (ac) {
+		while (!av[0]) {
 			if (isdigit(**av)) {
 				i = atoi(*av);
 				if (i < 0 || i > RESVD_SET)
@@ -1699,7 +1699,7 @@ ipfw_sets_handler(int ac, char *av[])
 			else
 				errx(EX_DATAERR,
 					"invalid set command %s\n", *av);
-			av++; ac--;
+			av++;
 		}
 		if ( (masks[0] & masks[1]) != 0 )
 			errx(EX_DATAERR,
@@ -1713,12 +1713,11 @@ ipfw_sets_handler(int ac, char *av[])
 }
 
 void
-ipfw_sysctl_handler(int ac, char *av[], int which)
+ipfw_sysctl_handler(char *av[], int which)
 {
-	ac--;
 	av++;
 
-	if (ac == 0) {
+	if (av[0] == NULL) {
 		warnx("missing keyword to enable/disable\n");
 	} else if (_substrcmp(*av, "firewall") == 0) {
 		sysctlbyname("net.inet.ip.fw.enable", NULL, 0,
@@ -2207,29 +2206,28 @@ fill_flags(ipfw_insn *cmd, enum ipfw_opc
 
 
 void
-ipfw_delete(int ac, char *av[])
+ipfw_delete(char *av[])
 {
 	uint32_t rulenum;
 	int i;
 	int exitval = EX_OK;
 	int do_set = 0;
 
-
-	av++; ac--;
+	av++;
 	NEED1("missing rule specification");
-	if (ac > 0 && _substrcmp(*av, "set") == 0) {
+	if ( *av && _substrcmp(*av, "set") == 0) {
 		/* Do not allow using the following syntax:
 		 *	ipfw set N delete set M
 		 */
 		if (co.use_set)
 			errx(EX_DATAERR, "invalid syntax");
 		do_set = 1;	/* delete set */
-		ac--; av++;
+		av++;
 	}
 
 	/* Rule number */
-	while (ac && isdigit(**av)) {
-		i = atoi(*av); av++; ac--;
+	while (*av && isdigit(**av)) {
+		i = atoi(*av); av++;
 		if (co.do_nat) {
 			exitval = do_cmd(IP_FW_NAT_DEL, &i, sizeof i);
 			if (exitval) {
@@ -2345,7 +2343,7 @@ next_cmd(ipfw_insn *cmd)
  * Takes arguments and copies them into a comment
  */
 static void
-fill_comment(ipfw_insn *cmd, int ac, char **av)
+fill_comment(ipfw_insn *cmd, char **av)
 {
 	int i, l;
 	char *p = (char *)(cmd + 1);
@@ -2354,7 +2352,7 @@ fill_comment(ipfw_insn *cmd, int ac, cha
 	cmd->len =  (cmd->len & (F_NOT | F_OR));
 
 	/* Compute length of comment string. */
-	for (i = 0, l = 0; i < ac; i++)
+	for (i = 0, l = 0; av[i] != NULL; i++)
 		l += strlen(av[i]) + 1;
 	if (l == 0)
 		return;
@@ -2363,7 +2361,7 @@ fill_comment(ipfw_insn *cmd, int ac, cha
 		    "comment too long (max 80 chars)");
 	l = 1 + (l+3)/4;
 	cmd->len =  (cmd->len & (F_NOT | F_OR)) | l;
-	for (i = 0; i < ac; i++) {
+	for (i = 0; av[i] != NULL; i++) {
 		strcpy(p, av[i]);
 		p += strlen(av[i]);
 		*p++ = ' ';
@@ -2388,11 +2386,11 @@ fill_cmd(ipfw_insn *cmd, enum ipfw_opcod
  * two microinstructions, and returns the pointer to the last one.
  */
 static ipfw_insn *
-add_mac(ipfw_insn *cmd, int ac, char *av[])
+add_mac(ipfw_insn *cmd, char *av[])
 {
 	ipfw_insn_mac *mac;
 
-	if (ac < 2)
+	if ( ( av[0] == NULL ) || ( av[1] == NULL ) )
 		errx(EX_DATAERR, "MAC dst src");
 
 	cmd->opcode = O_MACADDR2;
@@ -2406,9 +2404,9 @@ add_mac(ipfw_insn *cmd, int ac, char *av
 }
 
 static ipfw_insn *
-add_mactype(ipfw_insn *cmd, int ac, char *av)
+add_mactype(ipfw_insn *cmd, char *av)
 {
-	if (ac < 1)
+	if (!av)
 		errx(EX_DATAERR, "missing MAC type");
 	if (strcmp(av, "any") != 0) { /* we have a non-null type */
 		fill_newports((ipfw_insn_u16 *)cmd, av, IPPROTO_ETHERTYPE);
@@ -2591,7 +2589,7 @@ add_dst(ipfw_insn *cmd, char *av, u_char
  *
  */
 void
-ipfw_add(int ac, char *av[])
+ipfw_add(char *av[])
 {
 	/*
 	 * rules are added into the 'rulebuf' and then copied in
@@ -2630,37 +2628,36 @@ ipfw_add(int ac, char *av[])
 	cmd = (ipfw_insn *)cmdbuf;
 	action = (ipfw_insn *)actbuf;
 
-	av++; ac--;
+	av++;
 
 	/* [rule N]	-- Rule number optional */
-	if (ac && isdigit(**av)) {
+	if (av[0] && isdigit(**av)) {
 		rule->rulenum = atoi(*av);
 		av++;
-		ac--;
 	}
 
 	/* [set N]	-- set number (0..RESVD_SET), optional */
-	if (ac > 1 && _substrcmp(*av, "set") == 0) {
+	if (av[0] && !av[1] && _substrcmp(*av, "set") == 0) {
 		int set = strtoul(av[1], NULL, 10);
 		if (set < 0 || set > RESVD_SET)
 			errx(EX_DATAERR, "illegal set %s", av[1]);
 		rule->set = set;
-		av += 2; ac -= 2;
+		av += 2;
 	}
 
 	/* [prob D]	-- match probability, optional */
-	if (ac > 1 && _substrcmp(*av, "prob") == 0) {
+	if (av[0] && av[1] && _substrcmp(*av, "prob") == 0) {
 		match_prob = strtod(av[1], NULL);
 
 		if (match_prob <= 0 || match_prob > 1)
 			errx(EX_DATAERR, "illegal match prob. %s", av[1]);
-		av += 2; ac -= 2;
+		av += 2;
 	}
 
 	/* action	-- mandatory */
 	NEED1("missing action");
 	i = match_token(rule_actions, *av);
-	ac--; av++;
+	av++;
 	action->len = 1;	/* default */
 	switch(i) {
 	case TOK_CHECKSTATE:
@@ -2696,14 +2693,14 @@ ipfw_add(int ac, char *av[])
 		action->opcode = O_REJECT;
 		NEED1("missing reject code");
 		fill_reject_code(&action->arg1, *av);
-		ac--; av++;
+		av++;
 		break;
 
 	case TOK_UNREACH6:
 		action->opcode = O_UNREACH6;
 		NEED1("missing unreach code");
 		fill_unreach6_code(&action->arg1, *av);
-		ac--; av++;
+		av++;
 		break;
 
 	case TOK_COUNT:
@@ -2736,7 +2733,7 @@ ipfw_add(int ac, char *av[])
 	case TOK_TEE:
 		action->opcode = O_TEE;
 chkarg:	
-		if (!ac)
+		if (!av[0])
 			errx(EX_USAGE, "missing argument for %s", *(av - 1));
 		if (isdigit(**av)) {
 			action->arg1 = strtoul(*av, NULL, 10);
@@ -2755,7 +2752,7 @@ chkarg:	
 				errx(EX_DATAERR, "illegal divert/tee port");
 		} else
 			errx(EX_DATAERR, "illegal argument for %s", *(av - 1));
-		ac--; av++;
+		av++;
 		break;
 
 	case TOK_FORWARD: {
@@ -2793,13 +2790,13 @@ chkarg:	
 			p->sa.sin_addr.s_addr = INADDR_ANY;
 		else
 			lookup_host(*av, &(p->sa.sin_addr));
-		ac--; av++;
+		av++;
 		break;
 	    }
 	case TOK_COMMENT:
 		/* pretend it is a 'count' rule followed by the comment */
 		action->opcode = O_COUNT;
-		ac++; av--;	/* go back... */
+		av--;		/* go back... */
 		break;
 
 	case TOK_SETFIB:
@@ -2814,7 +2811,7 @@ chkarg:	
 			errx(EX_DATAERR, "fibs not suported.\n");
 		if (action->arg1 >= numfibs)  /* Temporary */
 			errx(EX_DATAERR, "fib too large.\n");
- 		ac--; av++;
+ 		av++;
  		break;
 	    }
 
@@ -2834,8 +2831,8 @@ chkarg:	
 	 * If they exist, it go first in the cmdbuf, but then it is
 	 * skipped in the copy section to the end of the buffer.
 	 */
-	while (ac != 0 && (i = match_token(rule_action_params, *av)) != -1) {
-		ac--; av++;
+	while (av[0] != NULL && (i = match_token(rule_action_params, *av)) != -1) {
+		av++;
 		switch (i) {
 		case TOK_LOG:
 		    {
@@ -2848,15 +2845,15 @@ chkarg:	
 			have_log = (ipfw_insn *)c;
 			cmd->len = F_INSN_SIZE(ipfw_insn_log);
 			cmd->opcode = O_LOG;
-			if (ac && _substrcmp(*av, "logamount") == 0) {
-				ac--; av++;
+			if (av[0] && _substrcmp(*av, "logamount") == 0) {
+				av++;
 				NEED1("logamount requires argument");
 				l = atoi(*av);
 				if (l < 0)
 					errx(EX_DATAERR,
 					    "logamount must be positive");
 				c->max_log = l;
-				ac--; av++;
+				av++;
 			} else {
 				len = sizeof(c->max_log);
 				if (sysctlbyname("net.inet.ip.fw.verbose_limit",
@@ -2880,7 +2877,7 @@ chkarg:	
 			cmd->len = F_INSN_SIZE(ipfw_insn_altq);
 			cmd->opcode = O_ALTQ;
 			a->qid = altq_name_to_qid(*av);
-			ac--; av++;
+			av++;
 		    }
 			break;
 #endif
@@ -2896,7 +2893,7 @@ chkarg:	
 			   rule_action_params);
 			have_tag = cmd;
 			fill_cmd(cmd, O_TAG, (i == TOK_TAG) ? 0: F_NOT, tag);
-			ac--; av++;
+			av++;
 			break;
 		}
 
@@ -2910,13 +2907,13 @@ chkarg:	
 		goto done;
 
 #define OR_START(target)					\
-	if (ac && (*av[0] == '(' || *av[0] == '{')) {		\
+	if (av[0] && (*av[0] == '(' || *av[0] == '{')) { 	\
 		if (open_par)					\
 			errx(EX_USAGE, "nested \"(\" not allowed\n"); \
 		prev = NULL;					\
 		open_par = 1;					\
 		if ( (av[0])[1] == '\0') {			\
-			ac--; av++;				\
+			av++;					\
 		} else						\
 			(*av)++;				\
 	}							\
@@ -2925,30 +2922,30 @@ chkarg:	
 
 #define	CLOSE_PAR						\
 	if (open_par) {						\
-		if (ac && (					\
+		if (av[0] && (					\
 		    strcmp(*av, ")") == 0 ||			\
 		    strcmp(*av, "}") == 0)) {			\
 			prev = NULL;				\
 			open_par = 0;				\
-			ac--; av++;				\
+			av++;					\
 		} else						\
 			errx(EX_USAGE, "missing \")\"\n");	\
 	}
 
 #define NOT_BLOCK						\
-	if (ac && _substrcmp(*av, "not") == 0) {		\
+	if (av[0] && _substrcmp(*av, "not") == 0) {		\
 		if (cmd->len & F_NOT)				\
 			errx(EX_USAGE, "double \"not\" not allowed\n"); \
 		cmd->len |= F_NOT;				\
-		ac--; av++;					\
+		av++;						\
 	}
 
 #define OR_BLOCK(target)					\
-	if (ac && _substrcmp(*av, "or") == 0) {		\
+	if (av[0] && _substrcmp(*av, "or") == 0) {		\
 		if (prev == NULL || open_par == 0)		\
 			errx(EX_DATAERR, "invalid OR block");	\
 		prev->len |= F_OR;				\
-		ac--; av++;					\
+		av++;					\
 		goto target;					\
 	}							\
 	CLOSE_PAR;
@@ -2965,15 +2962,15 @@ chkarg:	
 	NEED1("missing protocol");
 	if (_substrcmp(*av, "MAC") == 0 ||
 	    _substrcmp(*av, "mac") == 0) {
-		ac--; av++;	/* the "MAC" keyword */
-		add_mac(cmd, ac, av); /* exits in case of errors */
+		av++;			/* the "MAC" keyword */
+		add_mac(cmd, av);	/* exits in case of errors */
 		cmd = next_cmd(cmd);
-		ac -= 2; av += 2;	/* dst-mac and src-mac */
+		av += 2;		/* dst-mac and src-mac */
 		NOT_BLOCK;
 		NEED1("missing mac type");
-		if (add_mactype(cmd, ac, av[0]))
+		if (add_mactype(cmd, av[0]))
 			cmd = next_cmd(cmd);
-		ac--; av++;	/* any or mac-type */
+		av++;			/* any or mac-type */
 		goto read_options;
 	}
 #endif
@@ -2985,7 +2982,7 @@ chkarg:	
 	NOT_BLOCK;
 	NEED1("missing protocol");
 	if (add_proto_compat(cmd, *av, &proto)) {
-		av++; ac--;
+		av++;
 		if (F_LEN(cmd) != 0) {
 			prev = cmd;
 			cmd = next_cmd(cmd);
@@ -2999,9 +2996,9 @@ chkarg:	
 	/*
 	 * "from", mandatory
 	 */
-	if (!ac || _substrcmp(*av, "from") != 0)
+	if ((av[0] == NULL) || _substrcmp(*av, "from") != 0)
 		errx(EX_USAGE, "missing ``from''");
-	ac--; av++;
+	av++;
 
 	/*
 	 * source IP, mandatory
@@ -3010,7 +3007,7 @@ chkarg:	
 	NOT_BLOCK;	/* optional "not" */
 	NEED1("missing source address");
 	if (add_src(cmd, *av, proto)) {
-		ac--; av++;
+		av++;
 		if (F_LEN(cmd) != 0) {	/* ! any */
 			prev = cmd;
 			cmd = next_cmd(cmd);
@@ -3023,10 +3020,10 @@ chkarg:	
 	 * source ports, optional
 	 */
 	NOT_BLOCK;	/* optional "not" */
-	if (ac) {
+	if ( av[0] != NULL ) {
 		if (_substrcmp(*av, "any") == 0 ||
 		    add_ports(cmd, *av, proto, O_IP_SRCPORT)) {
-			ac--; av++;
+			av++;
 			if (F_LEN(cmd) != 0)
 				cmd = next_cmd(cmd);
 		}
@@ -3035,9 +3032,9 @@ chkarg:	
 	/*
 	 * "to", mandatory
 	 */
-	if (!ac || _substrcmp(*av, "to") != 0)
+	if ( (av[0] == NULL) || _substrcmp(*av, "to") != 0 )
 		errx(EX_USAGE, "missing ``to''");
-	av++; ac--;
+	av++;
 
 	/*
 	 * destination, mandatory
@@ -3046,7 +3043,7 @@ chkarg:	
 	NOT_BLOCK;	/* optional "not" */
 	NEED1("missing dst address");
 	if (add_dst(cmd, *av, proto)) {
-		ac--; av++;
+		av++;
 		if (F_LEN(cmd) != 0) {	/* ! any */
 			prev = cmd;
 			cmd = next_cmd(cmd);
@@ -3059,17 +3056,17 @@ chkarg:	
 	 * dest. ports, optional
 	 */
 	NOT_BLOCK;	/* optional "not" */
-	if (ac) {
+	if (av[0]) {
 		if (_substrcmp(*av, "any") == 0 ||
 		    add_ports(cmd, *av, proto, O_IP_DSTPORT)) {
-			ac--; av++;
+			av++;
 			if (F_LEN(cmd) != 0)
 				cmd = next_cmd(cmd);
 		}
 	}
 
 read_options:
-	if (ac && first_cmd == cmd) {
+	if (av[0] && first_cmd == cmd) {
 		/*
 		 * nothing specified so far, store in the rule to ease
 		 * printout later.
@@ -3077,7 +3074,7 @@ read_options:
 		 rule->_pad = 1;
 	}
 	prev = NULL;
-	while (ac) {
+	while ( av[0] != NULL ) {
 		char *s;
 		ipfw_insn_u32 *cmd32;	/* alias for cmd */
 
@@ -3091,7 +3088,7 @@ read_options:
 			s++;
 		}
 		i = match_token(rule_options, s);
-		ac--; av++;
+		av++;
 		switch(i) {
 		case TOK_NOT:
 			if (cmd->len & F_NOT)
@@ -3153,7 +3150,7 @@ read_options:
 			NEED1("recv, xmit, via require interface name"
 				" or address");
 			fill_iface((ipfw_insn_if *)cmd, av[0]);
-			ac--; av++;
+			av++;
 			if (F_LEN(cmd) == 0)	/* not a valid address */
 				break;
 			if (i == TOK_XMIT)
@@ -3167,13 +3164,13 @@ read_options:
 		case TOK_ICMPTYPES:
 			NEED1("icmptypes requires list of types");
 			fill_icmptypes((ipfw_insn_u32 *)cmd, *av);
-			av++; ac--;
+			av++;
 			break;
 		
 		case TOK_ICMP6TYPES:
 			NEED1("icmptypes requires list of types");
 			fill_icmp6types((ipfw_insn_icmp6 *)cmd, *av);
-			av++; ac--;
+			av++;
 			break;
 
 		case TOK_IPTTL:
@@ -3183,7 +3180,7 @@ read_options:
 				errx(EX_DATAERR, "invalid ipttl %s", *av);
 			} else
 			    fill_cmd(cmd, O_IPTTL, 0, strtoul(*av, NULL, 0));
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_IPID:
@@ -3193,7 +3190,7 @@ read_options:
 				errx(EX_DATAERR, "invalid ipid %s", *av);
 			} else
 			    fill_cmd(cmd, O_IPID, 0, strtoul(*av, NULL, 0));
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_IPLEN:
@@ -3203,32 +3200,32 @@ read_options:
 				errx(EX_DATAERR, "invalid ip len %s", *av);
 			} else
 			    fill_cmd(cmd, O_IPLEN, 0, strtoul(*av, NULL, 0));
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_IPVER:
 			NEED1("ipver requires version");
 			fill_cmd(cmd, O_IPVER, 0, strtoul(*av, NULL, 0));
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_IPPRECEDENCE:
 			NEED1("ipprecedence requires value");
 			fill_cmd(cmd, O_IPPRECEDENCE, 0,
 			    (strtoul(*av, NULL, 0) & 7) << 5);
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_IPOPTS:
 			NEED1("missing argument for ipoptions");
 			fill_flags(cmd, O_IPOPT, f_ipopts, *av);
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_IPTOS:
 			NEED1("missing argument for iptos");
 			fill_flags(cmd, O_IPTOS, f_iptos, *av);
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_UID:
@@ -3245,7 +3242,7 @@ read_options:
 				errx(EX_DATAERR, "uid \"%s\" nonexistent", *av);
 			cmd32->d[0] = pwd->pw_uid;
 			cmd->len |= F_INSN_SIZE(ipfw_insn_u32);
-			ac--; av++;
+			av++;
 		    }
 			break;
 
@@ -3263,7 +3260,7 @@ read_options:
 				errx(EX_DATAERR, "gid \"%s\" nonexistent", *av);
 			cmd32->d[0] = grp->gr_gid;
 			cmd->len |= F_INSN_SIZE(ipfw_insn_u32);
-			ac--; av++;
+			av++;
 		    }
 			break;
 
@@ -3279,7 +3276,7 @@ read_options:
 				errx(EX_DATAERR, "jail requires prison ID");
 			cmd32->d[0] = (uint32_t)jid;
 			cmd->len |= F_INSN_SIZE(ipfw_insn_u32);
-			ac--; av++;
+			av++;
 		    }
 			break;
 
@@ -3300,13 +3297,13 @@ read_options:
 			} else
 			    fill_cmd(cmd, O_TCPDATALEN, 0,
 				    strtoul(*av, NULL, 0));
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_TCPOPTS:
 			NEED1("missing argument for tcpoptions");
 			fill_flags(cmd, O_TCPOPTS, f_tcpopts, *av);
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_TCPSEQ:
@@ -3315,21 +3312,21 @@ read_options:
 			cmd->len = F_INSN_SIZE(ipfw_insn_u32);
 			cmd->opcode = (i == TOK_TCPSEQ) ? O_TCPSEQ : O_TCPACK;
 			cmd32->d[0] = htonl(strtoul(*av, NULL, 0));
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_TCPWIN:
 			NEED1("tcpwin requires length");
 			fill_cmd(cmd, O_TCPWIN, 0,
 			    htons(strtoul(*av, NULL, 0)));
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_TCPFLAGS:
 			NEED1("missing argument for tcpflags");
 			cmd->opcode = O_TCPFLAGS;
 			fill_flags(cmd, O_TCPFLAGS, f_tcpflags, *av);
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_KEEPSTATE:
@@ -3359,11 +3356,11 @@ read_options:
 			cmd->opcode = O_LIMIT;
 			c->limit_mask = c->conn_limit = 0;
 
-			while (ac > 0) {
+			while ( av[0] != NULL ) {
 				if ((val = match_token(limit_masks, *av)) <= 0)
 					break;
 				c->limit_mask |= val;
-				ac--; av++;
+				av++;
 			}
 
 			if (c->limit_mask == 0)
@@ -3372,14 +3369,14 @@ read_options:
 			GET_UINT_ARG(c->conn_limit, IPFW_ARG_MIN, IPFW_ARG_MAX,
 			    TOK_LIMIT, rule_options);
 
-			ac--; av++;
+			av++;
 			break;
 		}
 
 		case TOK_PROTO:
 			NEED1("missing protocol");
 			if (add_proto(cmd, *av, &proto)) {
-				ac--; av++;
+				av++;
 			} else
 				errx(EX_DATAERR, "invalid protocol ``%s''",
 				    *av);
@@ -3388,28 +3385,28 @@ read_options:
 		case TOK_SRCIP:
 			NEED1("missing source IP");
 			if (add_srcip(cmd, *av)) {
-				ac--; av++;
+				av++;
 			}
 			break;
 
 		case TOK_DSTIP:
 			NEED1("missing destination IP");
 			if (add_dstip(cmd, *av)) {
-				ac--; av++;
+				av++;
 			}
 			break;
 
 		case TOK_SRCIP6:
 			NEED1("missing source IP6");
 			if (add_srcip6(cmd, *av)) {
-				ac--; av++;
+				av++;
 			}
 			break;
 				
 		case TOK_DSTIP6:
 			NEED1("missing destination IP6");
 			if (add_dstip6(cmd, *av)) {
-				ac--; av++;
+				av++;
 			}
 			break;
 
@@ -3417,7 +3414,7 @@ read_options:
 			NEED1("missing source port");
 			if (_substrcmp(*av, "any") == 0 ||
 			    add_ports(cmd, *av, proto, O_IP_SRCPORT)) {
-				ac--; av++;
+				av++;
 			} else
 				errx(EX_DATAERR, "invalid source port %s", *av);
 			break;
@@ -3426,23 +3423,22 @@ read_options:
 			NEED1("missing destination port");
 			if (_substrcmp(*av, "any") == 0 ||
 			    add_ports(cmd, *av, proto, O_IP_DSTPORT)) {
-				ac--; av++;
+				av++;
 			} else
 				errx(EX_DATAERR, "invalid destination port %s",
 				    *av);
 			break;
 
 		case TOK_MAC:
-			if (add_mac(cmd, ac, av)) {
-				ac -= 2; av += 2;
-			}
+			if (add_mac(cmd, av))
+				av += 2;
 			break;
 
 		case TOK_MACTYPE:
 			NEED1("missing mac type");
-			if (!add_mactype(cmd, ac, *av))
+			if (!add_mactype(cmd, *av))
 				errx(EX_DATAERR, "invalid mac type %s", *av);
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_VERREVPATH:
@@ -3471,7 +3467,7 @@ read_options:
 
 		case TOK_EXT6HDR:
 			fill_ext6hdr( cmd, *av );
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_FLOWID:
@@ -3479,17 +3475,16 @@ read_options:
 				errx( EX_USAGE, "flow-id filter is active "
 				    "only for ipv6 protocol\n");
 			fill_flow6( (ipfw_insn_u32 *) cmd, *av );
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_COMMENT:
-			fill_comment(cmd, ac, av);
-			av += ac;
-			ac = 0;
+			fill_comment(cmd, av);
+			av[0]=NULL;
 			break;
 
 		case TOK_TAGGED:
-			if (ac > 0 && strpbrk(*av, "-,")) {
+			if (av[0] && strpbrk(*av, "-,")) {
 				if (!add_ports(cmd, *av, 0, O_TAGGED))
 					errx(EX_DATAERR, "tagged: invalid tag"
 					    " list: %s", *av);
@@ -3501,13 +3496,13 @@ read_options:
 				    TOK_TAGGED, rule_options);
 				fill_cmd(cmd, O_TAGGED, 0, tag);
 			}
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_FIB:
 			NEED1("fib requires fib number");
 			fill_cmd(cmd, O_FIB, 0, strtoul(*av, NULL, 0));
-			ac--; av++;
+			av++;
 			break;
 
 		case TOK_LOOKUP: {
@@ -3515,7 +3510,7 @@ read_options:
 			char *p;
 			int j;
 
-			if (ac < 2)
+			if (av[0] && av[1])
 				errx(EX_USAGE, "format: lookup argument tablenum");
 			cmd->opcode = O_IP_DST_LOOKUP;
 			cmd->len |= F_INSN_SIZE(ipfw_insn) + 2;
@@ -3527,11 +3522,11 @@ read_options:
 			if (lookup_key[j] <= 0)
 				errx(EX_USAGE, "format: cannot lookup on %s", *av);
 			c->d[1] = j; // i converted to option
-			ac--; av++;
+			av++;
 			cmd->arg1 = strtoul(*av, &p, 0);
 			if (p && *p)
 				errx(EX_USAGE, "format: lookup argument tablenum");
-			ac--; av++;
+			av++;
 		    }
 			break;
 

Modified: user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h	Mon Feb 22 16:16:16 2010	(r204208)
+++ user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h	Mon Feb 22 16:17:37 2010	(r204209)
@@ -204,7 +204,7 @@ enum tokens {
  * arguments.
  */
 #define NEED(_p, msg)      {if (!_p) errx(EX_USAGE, msg);}
-#define NEED1(msg)      {if (!ac) errx(EX_USAGE, msg);}
+#define NEED1(msg)      {if (!(*av)) errx(EX_USAGE, msg);}
 
 unsigned long long align_uint64(const uint64_t *pll);
 
@@ -248,14 +248,14 @@ struct _ipfw_insn_icmp6;
 extern int resvd_set_number;
 
 /* first-level command handlers */
-void ipfw_add(int ac, char *av[]);
+void ipfw_add(char *av[]);
 void ipfw_show_nat(int ac, char **av);
 void ipfw_config_pipe(int ac, char **av);
 void ipfw_config_nat(int ac, char **av);
-void ipfw_sets_handler(int ac, char *av[]);
+void ipfw_sets_handler(char *av[]);
 void ipfw_table_handler(int ac, char *av[]);
-void ipfw_sysctl_handler(int ac, char *av[], int which);
-void ipfw_delete(int ac, char *av[]);
+void ipfw_sysctl_handler(char *av[], int which);
+void ipfw_delete(char *av[]);
 void ipfw_flush(int force);
 void ipfw_zero(int ac, char *av[], int optname);
 void ipfw_list(int ac, char *av[], int show_counters);

Modified: user/luigi/ipfw3-head/sbin/ipfw/main.c
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/main.c	Mon Feb 22 16:16:16 2010	(r204208)
+++ user/luigi/ipfw3-head/sbin/ipfw/main.c	Mon Feb 22 16:17:37 2010	(r204209)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2003 Luigi Rizzo
+ * Copyright (c) 2002-2003,2010 Luigi Rizzo
  * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
  * Copyright (c) 1994 Ugen J.S.Antsilevich
  *
@@ -80,31 +80,27 @@ help(void)
 }
 
 /*
- * Free a the (locally allocated) copy of command line arguments.
- */
-static void
-free_args(int ac, char **av)
-{
-	int i;
-
-	for (i=0; i < ac; i++)
-		free(av[i]);
-	free(av);
-}
-
-/*
  * Called with the arguments, including program name because getopt
  * wants it to be present.
  * Returns 0 if successful, 1 if empty command, errx() in case of errors.
+ * First thing we do is process parameters creating an argv[] array
+ * which includes the program name and a NULL entry at the end.
+ * If we are called with a single string, we split it on whitespace.
+ * Also, arguments with a trailing ',' are joined to the next one.
+ * The pointers (av[]) and data are in a a single chunk of memory.
+ * av[0] points to the original program name, all other entries
+ * point into the allocated chunk.
  */
 static int
 ipfw_main(int oldac, char **oldav)
 {
-	int ch, ac, save_ac;
+	int ch, ac;
 	const char *errstr;
 	char **av, **save_av;
 	int do_acct = 0;		/* Show packet/byte count */
 	int try_next = 0;		/* set if pipe cmd not found */
+	int av_size;			/* compute the av size */
+	char *av_p;			/* used to build the av list */
 
 #define WHITESP		" \t\f\v\n\r"
 	if (oldac < 2)
@@ -112,10 +108,9 @@ ipfw_main(int oldac, char **oldav)
 
 	if (oldac == 2) {
 		/*
-		 * If we are called with a single string, try to split it into
-		 * arguments for subsequent parsing.
-		 * But first, remove spaces after a ',', by copying the string
-		 * in-place.
+		 * If we are called with one argument, try to split it into
+		 * words for subsequent parsing. Spaces after a ',' are
+		 * removed by copying the string in-place.
 		 */
 		char *arg = oldav[1];	/* The string is the first arg. */
 		int l = strlen(arg);
@@ -150,31 +145,59 @@ ipfw_main(int oldac, char **oldav)
 				ac++;
 
 		/*
-		 * Allocate the argument list, including one entry for
-		 * the program name because getopt expects it.
+		 * Allocate the argument list structure as a single block
+		 * of memory, containing pointers and the argument
+		 * strings. We include one entry for the program name
+		 * because getopt expects it, and a NULL at the end
+		 * to simplify further parsing.
 		 */
-		av = safe_calloc(ac + 1, sizeof(char *));
+		ac++;		/* add 1 for the program name */
+		av_size = (ac+1) * sizeof(char *) + l + 1;
+		av = safe_calloc(av_size, 1);
 
 		/*
-		 * Second, copy arguments from arg[] to av[]. For each one,
+		 * Init the argument pointer to the end of the array
+		 * and copy arguments from arg[] to av[]. For each one,
 		 * j is the initial character, i is the one past the end.
 		 */
-		for (ac = 1, i = j = 0; i < l; i++)
+		av_p = (char *)&av[ac+1];
+		for (ac = 1, i = j = 0; i < l; i++) {
 			if (index(WHITESP, arg[i]) != NULL || i == l-1) {
 				if (i == l-1)
 					i++;
-				av[ac] = safe_calloc(i-j+1, 1);
-				bcopy(arg+j, av[ac], i-j);
+				bcopy(arg+j, av_p, i-j);
+				av[ac] = av_p;
+				av_p += i-j;	/* the lenght of the string */
+				*av_p++ = '\0';
 				ac++;
 				j = i + 1;
 			}
+		}
 	} else {
 		/*
 		 * If an argument ends with ',' join with the next one.
 		 */
-		int first, i, l;
+		int first, i, l=0;
+
+		/*
+		 * Allocate the argument list structure as a single block
+		 * of memory, containing both pointers and the argument
+		 * strings. We include some space for the program name
+		 * because getopt expects it.
+		 * We add an extra pointer to the end of the array,
+		 * to make simpler further parsing.
+		 */
+		for (i=0; i<oldac; i++)
+			l += strlen(oldav[i]);
+
+		av_size = (oldac+1) * sizeof(char *) + l + oldac;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002221617.o1MGHcYl094335>