1    	/*
2    	 * Copyright 2004-2012 Red Hat, Inc.
3    	 *
4    	 * This copyrighted material is made available to anyone wishing to use,
5    	 * modify, copy, or redistribute it subject to the terms and conditions
6    	 * of the GNU General Public License v2 or (at your option) any later version.
7    	 */
8    	
9    	#include "dlm_daemon.h"
10   	
11   	static int syslog_facility;
12   	static int syslog_priority;
13   	static int logfile_priority;
14   	static char logfile[PATH_MAX];
15   	static FILE *logfile_fp;
16   	
17   	/* logfile_priority is the only one of these options that
18   	   can be controlled from command line, environment variable
19   	   and dynamic setting.
20   	 */
21   	void set_logfile_priority(void)
22   	{
23   		if (opt(debug_logfile_ind))
24   			logfile_priority = LOG_DEBUG;
25   		else
26   			logfile_priority = DEFAULT_LOGFILE_PRIORITY;
27   	}
28   	
29   	void init_logging(void)
30   	{
31   		mode_t old_umask;
32   		int rv;
33   	
34   		syslog_facility = DEFAULT_SYSLOG_FACILITY;
35   		syslog_priority = DEFAULT_SYSLOG_PRIORITY;
36   		logfile_priority = DEFAULT_LOGFILE_PRIORITY;
37   		strcpy(logfile, DEFAULT_LOGFILE);
38   	
39   		set_logfile_priority();
40   	
41   		old_umask = umask(0077);
42   		rv = mkdir(SYS_VARDIR, 0700);
(1) Event cond_false: Condition "rv < 0", taking false branch.
43   		if (rv < 0 && errno != EEXIST) {
44   			umask(old_umask);
45   			goto skip_logfile;
(2) Event if_end: End of if statement.
46   		}
47   	
48   		rv = mkdir(SYS_LOGDIR, 0700);
(3) Event cond_false: Condition "rv < 0", taking false branch.
49   		if (rv < 0 && errno != EEXIST) {
50   			umask(old_umask);
51   			goto skip_logfile;
(4) Event if_end: End of if statement.
52   		}
53   	
54   		rv = mkdir(LOGDIR, 0700);
(5) Event cond_false: Condition "rv < 0", taking false branch.
55   		if (rv < 0 && errno != EEXIST) {
56   			umask(old_umask);
57   			goto skip_logfile;
(6) Event if_end: End of if statement.
58   		}
59   		umask(old_umask);
60   	
(7) Event cond_true: Condition "logfile[0]", taking true branch.
61   		if (logfile[0]) {
62   			logfile_fp = fopen(logfile, "a+");
(8) Event cond_true: Condition "logfile_fp != NULL", taking true branch.
63   			if (logfile_fp != NULL) {
64   				int fd = fileno(logfile_fp);
(9) Event check_return: Calling "fcntl(fd, 2, fcntl(fd, 1, 0) | 1)" without checking return value. This library function may fail and return an error code.
65   				fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
66   			}
67   		}
68   	
69   	skip_logfile:
70   		openlog(DAEMON_NAME, LOG_CONS | LOG_PID, syslog_facility);
71   	}
72   	
73   	void close_logging(void)
74   	{
75   		closelog();
76   		if (logfile_fp)
77   			fclose(logfile_fp);
78   	}
79   	
80   	#define NAME_ID_SIZE 32
81   	#define LOG_STR_LEN 512
82   	static char log_str[LOG_STR_LEN];
83   	
84   	static char log_dump[LOG_DUMP_SIZE];
85   	static unsigned int log_point;
86   	static unsigned int log_wrap;
87   	
88   	static char log_dump_plock[LOG_DUMP_SIZE];
89   	static unsigned int log_point_plock;
90   	static unsigned int log_wrap_plock;
91   	
92   	static void log_copy(char *buf, int *len, char *log_buf,
93   			     unsigned int *point, unsigned int *wrap)
94   	{
95   		unsigned int p = *point;
96   		unsigned int w = *wrap;
97   		int tail_len;
98   	
99   		if (!w && !p) {
100  			*len = 0;
101  		} else if (*wrap) {
102  			tail_len = LOG_DUMP_SIZE - p;
103  			memcpy(buf, log_buf + p, tail_len);
104  			if (p)
105  				memcpy(buf+tail_len, log_buf, p);
106  			*len = LOG_DUMP_SIZE;
107  		} else {
108  			memcpy(buf, log_buf, p-1);
109  			*len = p-1;
110  		}
111  	}
112  	
113  	void copy_log_dump(char *buf, int *len)
114  	{
115  		log_copy(buf, len, log_dump, &log_point, &log_wrap);
116  	}
117  	
118  	void copy_log_dump_plock(char *buf, int *len)
119  	{
120  		log_copy(buf, len, log_dump_plock, &log_point_plock, &log_wrap_plock);
121  	}
122  	
123  	static void log_save_str(int len, char *log_buf, unsigned int *point,
124  				 unsigned int *wrap)
125  	{
126  		unsigned int p = *point;
127  		unsigned int w = *wrap;
128  		int i;
129  	
130  		if (len < LOG_DUMP_SIZE - p) {
131  			memcpy(log_buf + p, log_str, len);
132  			p += len;
133  	
134  			if (p == LOG_DUMP_SIZE) {
135  				p = 0;
136  				w = 1;
137  			}
138  			goto out;
139  		}
140  	
141  		for (i = 0; i < len; i++) {
142  			log_buf[p++] = log_str[i];
143  	
144  			if (p == LOG_DUMP_SIZE) {
145  				p = 0;
146  				w = 1;
147  			}
148  		}
149  	 out:
150  		*point = p;
151  		*wrap = w;
152  	}
153  	
154  	void log_level(const char *name_in, uint32_t level_in, const char *fmt, ...)
155  	{
156  		va_list ap;
157  		char name[NAME_ID_SIZE + 2];
158  		uint32_t level = level_in & 0x0000FFFF;
159  		uint32_t extra = level_in & 0xFFFF0000;
160  		int ret, pos = 0;
161  		int len = LOG_STR_LEN - 2;
162  		int namelen = 0;
163  		int plock = extra & LOG_PLOCK;
164  	
165  		memset(name, 0, sizeof(name));
166  	
167  		if (name_in) {
168  			namelen = snprintf(name, NAME_ID_SIZE + 1, "%s", name_in);
169  			if (namelen > NAME_ID_SIZE)
170  				namelen = NAME_ID_SIZE;
171  			name[namelen] = ' ';
172  			name[namelen+1] = '\0';
173  		}
174  	
175  		ret = snprintf(log_str + pos, len - pos, "%llu %s",
176  			       (unsigned long long)monotime(), name);
177  	
178  		pos += ret;
179  	
180  		va_start(ap, fmt);
181  		ret = vsnprintf(log_str + pos, len - pos, fmt, ap);
182  		va_end(ap);
183  	
184  		if (ret >= len - pos)
185  			pos = len - 1;
186  		else
187  			pos += ret;
188  	
189  		log_str[pos++] = '\n';
190  		log_str[pos++] = '\0';
191  	
192  		if (level < LOG_NONE)
193  			log_save_str(pos - 1, log_dump, &log_point, &log_wrap);
194  		if (plock)
195  			log_save_str(pos - 1, log_dump_plock, &log_point_plock, &log_wrap_plock);
196  	
197  		if (level <= syslog_priority)
198  			syslog(level, "%s", log_str);
199  	
200  		if (level <= logfile_priority && logfile_fp) {
201  			time_t logtime = time(NULL);
202  			char tbuf[64];
203  			strftime(tbuf, sizeof(tbuf), "%b %d %T", localtime(&logtime));
204  			fprintf(logfile_fp, "%s %s", tbuf, log_str);
205  			fflush(logfile_fp);
206  		}
207  	
208  		if (!dlm_options[daemon_debug_ind].use_int)
209  			return;
210  	
211  		if ((level < LOG_NONE) || (plock && opt(plock_debug_ind)))
212  			fprintf(stderr, "%s", log_str);
213  	}
214  	
215