1    	/*
2    	 * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
3    	 * 
4    	 * This program is free software; you can redistribute it and/or modify it
5    	 * under the terms of the GNU General Public License as published by the
6    	 * Free Software Foundation; either version 2 of the License, or (at your
7    	 * option) any later version.
8    	 * 
9    	 * This program is distributed in the hope that it will be useful, but
10   	 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11   	 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   	 * for more details.
13   	 * 
14   	 * You should have received a copy of the GNU General Public License along
15   	 * with this program; if not, write to the Free Software Foundation, Inc.,
16   	 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17   	 */
18   	
19   	#include <ctype.h>
20   	#define	SYSLOG_NAMES
21   	#include "dstruct.h"
22   	#include "eval.h"
23   	#include "syntax.h"
24   	#include "syslog.h"
25   	#include "pmapi.h"
26   	
27   	#if defined(IS_SOLARIS) || defined(IS_AIX) || defined(IS_MINGW)
28   	#include "logger.h"
29   	#endif
30   	
31   	/*
32   	 * based on source for logger(1)
33   	 */
34   	static int
35   	decode(char *name, CODE *codetab)
36   	{
37   	    CODE *c;
38   	
39   	    if (isdigit((int)*name))
40   		return (atoi(name));
41   	
42   	    for (c = codetab; c->c_name; c++)
43   		if (!strcasecmp(name, c->c_name))
44   		    return (c->c_val);
45   	
46   	    return (-1);
47   	}
48   	
49   	/*
50   	 * Decode a symbolic name to a numeric value
51   	 * ... based on source for logger(1)
52   	 */
53   	static int
54   	pencode(char *s)
55   	{
56   	    char *save;
57   	    int fac, lev;
58   	
59   	    save = s;
60   	    while (*s && *s != '.') ++s;
61   	    if (*s) {
62   		*s = '\0';
63   		fac = decode(save, facilitynames);
64   		if (fac < 0) {
65   		    synwarn();
66   		    fprintf(stderr, "Ignoring unknown facility (%s) for -p in syslog action\n", save);
67   		    fac = 0;
68   		}
69   		s++;
70   	    }
71   	    else {
72   		fac = 0;
73   		s = save;
74   	    }
75   	    lev = decode(s, prioritynames);
76   	    if (lev < 0) {
77   		synwarn();
78   		fprintf(stderr, "Ignoring unknown priority (%s) for -p in syslog action\n", s);
79   		lev = LOG_NOTICE;
80   	    }
81   	    return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
82   	}
83   	
84   	/*
85   	 * handle splitting of -t tag and -p prio across one or two
86   	 * arguments to the syslog action in the rule
87   	 */
88   	static void
89   	nextch(char **p, Expr **x)
90   	{
91   	    static char	end = '\0';
92   	    (*p)++;
93   	    while (**p == '\0') {
94   		if ((*x)->arg1 == NULL) {
95   		    *p = &end;
96   		    return;
97   		}
98   		*x = (*x)->arg1;
99   		*p = (*x)->ring;
100  	    }
101  	}
102  	
103  	/*
104  	 * post-process the expression tree for a syslog action to gather
105  	 * any -t tag or -p pri options (as for logger(1)) and build the
106  	 * encoded equivalent as a new expression accessed via arg2 from
107  	 * the head of the arguments list
108  	 */
109  	void
110  	do_syslog_args(Expr *act)
111  	{
112  	    int		pri = -1;
113  	    char	*tag = NULL;
114  	    char	*p;
115  	    char	*q;
116  	    Expr	*others;
117  	    Expr	*tmp;
118  	    Expr	*new;
119  	
120  	    others = act->arg1;
121  	    /*
122  	     * scan for -p pri and -t tag
123  	     */
At conditional (1): "others != NULL": Taking true branch.
124  	    for (others = act->arg1; others != NULL; ) {
At conditional (2): "others->ring == NULL": Taking true branch.
125  		if (others->ring == NULL) break;
126  		p = others->ring;
127  		if (*p != '-') break;
128  		nextch(&p, &others);
129  		if (*p == 'p' && pri == -1) {
130  		    nextch(&p, &others);
131  		    while (*p && isspace((int)*p)) nextch(&p, &others);
132  		    if (*p == '\0') {
133  			synwarn();
134  			fprintf(stderr, "Missing [facility.]priority after -p in syslog action\n");
135  		    }
136  		    else {
137  			q = p+1;
138  			while (*q && !isspace((int)*q)) q++;
139  			if (*q) {
140  			    synwarn();
141  			    fprintf(stderr, "Ignoring extra text (%s) after -p pri in syslog action\n", q);
142  			    *q = '\0';
143  			}
144  			pri = pencode(p);
145  		    }
146  		}
147  		else if (*p == 't' && tag == NULL) {
148  		    nextch(&p, &others);
149  		    while (*p && isspace((int)*p)) nextch(&p, &others);
150  		    if (*p == '\0') {
151  			synwarn();
152  			fprintf(stderr, "Missing tag after -t in syslog action\n");
153  		    }
154  		    else {
155  			q = p+1;
156  			while (*q && !isspace((int)*q)) q++;
157  			if (*q) {
158  			    synwarn();
159  			    fprintf(stderr, "Ignoring extra text (%s) after -t tag in syslog action\n", q);
160  			    *q = '\0';
161  			}
162  			tag = p;
163  		    }
164  		}
165  		else
166  		    break;
167  		others = others->arg1;
168  	    }
169  	
170  	    /* defaults if -t and/or -p not seen */
At conditional (3): "pri < 0": Taking true branch.
171  	    if (pri < 0) pri = LOG_NOTICE;
At conditional (4): "tag == NULL": Taking true branch.
172  	    if (tag == NULL) tag = "pcp-pmie";
173  	
174  	    /*
175  	     * construct new arg2 argument node, with
176  	     *	ring	-> pri (int) and tag (char *) concatenated
177  	     */
178  	    new = (Expr *) zalloc(sizeof(Expr));
179  	    new->op = NOP;
180  	    new->ring = (char *)alloc(sizeof(int)+strlen(tag)+1);
181  	    *((int *)new->ring) = pri;
Event alloc_fn: Calling allocation function "sdup". [details]
Event noescape: Variable "sdup(tag)" is not freed or pointed-to in function "strcpy".
Event leaked_storage: Failing to save storage allocated by "sdup(tag)" leaks it.
182  	    strcpy(&((char *)new->ring)[sizeof(int)], sdup(tag));
183  	    act->arg2 = new;
184  	    new->parent = act;
185  	
186  	    /* free old argument nodes used for -p and/or -t specifications */
187  	    for (tmp = act->arg1; tmp != others; ) {
188  		if (tmp->ring) {
189  		    free(tmp->ring);
190  		}
191  		new = tmp->arg1;
192  		free(tmp);
193  		tmp = new;
194  	    }
195  	
196  	    /* re-link remaining argument nodes */
197  	    if (others != act->arg1) {
198  		act->arg1 = others;
199  		if (others != NULL)
200  		    others->parent = act;
201  	    }
202  	
203  	}