xref: /titanic_52/usr/src/cmd/hal/addons/cpufreq/addon-cpufreq.c (revision 6a1af1a67532df169a657cce07140be64bdea084)
1 /***************************************************************************
2  *
3  * addon-cpufreq.c : Routines to support CPUFreq interface
4  *
5  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
6  * Use is subject to license terms.
7  *
8  * Licensed under the Academic Free License version 2.1
9  *
10  ***************************************************************************/
11 
12 
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
16 
17 #include <stdio.h>
18 #include <errno.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <stdarg.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <stdlib.h>
26 #include <fcntl.h>
27 #include <sys/dkio.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <glib.h>
31 #include <dbus/dbus-glib-lowlevel.h>
32 #include <dbus/dbus-glib.h>
33 #include <priv.h>
34 #include <pwd.h>
35 
36 #include <syslog.h>
37 
38 #include <libhal.h>
39 #include "../../hald/logger.h"
40 #include "../../utils/adt_data.h"
41 
42 #include <pwd.h>
43 #ifdef HAVE_POLKIT
44 #include <libpolkit.h>
45 #endif
46 
47 #ifdef sun
48 #include <bsm/adt.h>
49 #include <bsm/adt_event.h>
50 #include <sys/pm.h>
51 #endif
52 
53 #define	POWER_CONF_FILE "/etc/power.conf"
54 #define	PMCONFIG "/usr/sbin/pmconfig -f"
55 #define	PM "/dev/pm"
56 
57 #define	FILE_ARR_SIZE 256
58 #define	EDIT_TYPE_SIZE 64
59 #define	ERR_BUF_SIZE 256
60 
61 #define	WAIT_TIME 30
62 
63 char TMP_CONF_FILE[64] = "/tmp/power.conf.XXXXXX";
64 const char *sender;
65 unsigned long 	uid;
66 
67 /*
68  * Specify different CPUFreq related HAL activities that can be done
69  */
70 enum hal_type {
71 	CPU_GOV,
72 	CPU_PERFORMANCE
73 };
74 typedef enum hal_type power_conf_hal_type;
75 
76 /*
77  * Various CPUFreq related editable parameters in the power.conf file
78  */
79 typedef struct {
80 	char	cpu_gov[EDIT_TYPE_SIZE];
81 	int	cpu_th;
82 } pconf_edit_type;
83 
84 /*
85  * CPUFreq interospect XML that exports the various CPUFreq HAL interface
86  * supported methods
87  */
88 const char *cpufreq_introspect_xml = \
89 	"	<method name= \"SetCPUFreqGovernor\">\n \
90 		<arg type= \"s\" name= \"governor\" direction= \"in\"/>\n \
91 	</method>\n \
92 	<method name= \"GetCPUFreqGovernor\">\n \
93 		<type= \"s\" direction= \"out\"/>\n \
94 	</method>\n \
95 	<method name= \"SetCPUFreqPerformance\">\n \
96 		<arg type=\"i\" direction=\"in\"/>\n \
97 	</method>\n \
98 	<method name= \"GetCPUFreqPerformance\">\n \
99 		<type=\"i\" direction=\"out\"/>\n \
100 	</method>\n \
101 	<method name= \"GetCPUFreqAvailableGovernors\">\n \
102 		<type=\"s\" direction=\"out\"/>\n \
103 	</method>\n";
104 
105 /*
106  * List of governors that are currently supported
107  */
108 char *const gov_list[] = {
109 	"ondemand",
110 	"performance",
111 	NULL
112 };
113 
114 static char current_gov[EDIT_TYPE_SIZE];
115 
116 /*
117  * Free up the mem allocated to hold the DBusError
118  */
119 static void
120 check_and_free_error(DBusError *error)
121 {
122 	if (dbus_error_is_set (error)) {
123 		dbus_error_free (error);
124 	}
125 }
126 
127 /*
128  * Edit the /etc/power.conf file to update the cpupm and cpupm_threshold values
129  * Return 0 on success
130  *	  1 if the governor is not available or supported
131  *	 -1 all other errors
132  * NOTE: Before modifying power.conf, it is first copied into a temp file, and
133  * pmconfig is executed on the temp file with -f option, which uses temp file
134  * to set the PM config and then replaces power.conf with the temp file.
135  */
136 static int
137 edit_power_conf_file(pconf_edit_type pc_edit_type,
138     power_conf_hal_type pc_hal_type, char *tmp_file)
139 {
140 	FILE	*pfile;
141 	char  	tstr[FILE_ARR_SIZE];
142 	char	temp_str[FILE_ARR_SIZE];
143 	long	fset = 0;
144 	long	next_fset = 0;
145 	char	*file_edit_type;
146 	char    *file_edit_value;
147 	char    file_edit_threshold[FILE_ARR_SIZE];
148 	char	file_update_str[FILE_ARR_SIZE];
149 	int	res = 0;
150 	char	cp_cmd_str[128];
151 	int	tmp_fd;
152 
153 	/*
154 	 * Copy /etc/power.conf to temp file
155 	 */
156 	if (tmp_file == NULL) {
157 		HAL_INFO ((" Invalid temp file name"));
158 		return (EINVAL);
159 	}
160 	sprintf (cp_cmd_str, "/usr/bin/cp %s %s", POWER_CONF_FILE, tmp_file);
161 	if (system (cp_cmd_str) != 0) {
162 		HAL_ERROR ((" Error in copying %s to %s, %s",
163 		    POWER_CONF_FILE, tmp_file, strerror (errno)));
164 		return (errno);
165 	}
166 
167 	pfile = fopen (tmp_file, "r+");
168 	if (pfile == NULL) {
169 		HAL_INFO (("Cannot open file %s: %s",
170 		    tmp_file, strerror (errno)));
171 		return (errno);
172 	}
173 
174 	switch (pc_hal_type) {
175 	case CPU_GOV:
176 		if ((pc_edit_type.cpu_gov == NULL) ||
177 		    ((strcmp (pc_edit_type.cpu_gov, "ondemand") != 0) &&
178 		    (strcmp (pc_edit_type.cpu_gov, "performance") != 0))) {
179 			HAL_INFO ((" CPU governor is not available/valid."
180 			    " Should be either ondemand or performance"));
181 			res = EINVAL;
182 			goto out;
183 		}
184 		file_edit_type = "cpupm";
185 		if (strcmp (pc_edit_type.cpu_gov, "ondemand") == 0) {
186 			file_edit_value = " enable";
187 		} else {
188 			file_edit_value = "disable";
189 		}
190 		break;
191 	case CPU_PERFORMANCE:
192 		if (pc_edit_type.cpu_th == NULL) {
193 			HAL_INFO ((" CPU Threshold is not valid."));
194 			res = EINVAL;
195 			goto out;
196 		}
197 		file_edit_type = "cpu-threshold";
198 		sprintf (file_edit_threshold, "%d", pc_edit_type.cpu_th);
199 		file_edit_value = file_edit_threshold;
200 		break;
201 	default:
202 		HAL_DEBUG ((" Cannot recognize the type of change being"
203 		    " made to /etc/power.conf"));
204 			res = EINVAL;
205 			goto out;
206 	}
207 
208 	while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
209 		if ((tstr == NULL) || (strlen (tstr) <= 0))
210 			continue;
211 		/*
212 		 * Look for line containing "cpupm" or "cpu-threshold"
213 		 */
214 
215 		if (strstr (tstr, file_edit_type) == NULL) {
216 			fset = fset + strlen (tstr);
217 			continue;
218 		}
219 		/*
220 		 * If the required value already present. Just
221 		 * return
222 		 */
223 		if (strstr (tstr, file_edit_value) != NULL) {
224 			res = 0;
225 			goto out;
226 		}
227 
228 		if (fseek (pfile, fset, SEEK_SET) != 0) {
229 			HAL_ERROR (("\n Error in fseek %s: %s",
230 			    POWER_CONF_FILE, strerror (errno)));
231 			res = errno;
232 			goto out;
233 		}
234 		/*
235 		 * Update the file with new values
236 		 */
237 		sprintf (file_update_str, "%s %s \n",
238 		    file_edit_type, file_edit_value);
239 
240 		/*
241 		 * Check if the currrent line is the last one. If not,
242 		 * to avoid overwriting and wasting space, move remaining
243 		 * lines upwards and update at the end
244 		 */
245 		next_fset = fset + strlen(tstr);
246 		if (fseek (pfile, next_fset, SEEK_SET) != 0) {
247 			HAL_ERROR (("\n Error in fseek %s: %s",
248 			    tmp_file, strerror (errno)));
249 			res = errno;
250 			goto out;
251 		}
252 		if (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
253 			do {
254 				snprintf (temp_str, FILE_ARR_SIZE,
255 				    "%s\n", tstr);
256 				fseek (pfile, fset, SEEK_SET);
257 				fputs (temp_str, pfile);
258 				fset = fset + strlen(tstr);
259 				next_fset = next_fset + strlen(tstr);
260 				fseek (pfile, next_fset, SEEK_SET);
261 
262 			} while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL);
263 		}
264 
265 		fseek (pfile, fset, SEEK_SET);
266 
267 		if (fputs (file_update_str, pfile) == EOF) {
268 			HAL_ERROR (("\n Error in writing to"
269 			    " %s: %s", POWER_CONF_FILE,
270 			    strerror (errno)));
271 			res = errno;
272 			goto out;
273 		}
274 
275 		if (fflush (pfile) == EOF) {
276 			HAL_ERROR (("\n Error in flushing to"
277 			    " %s: %s", POWER_CONF_FILE,
278 			    strerror (errno)));
279 		}
280 		res = 0;
281 		goto out;
282 	}
283 
284 	/*
285 	 * If the pointer comes here, then the property is not already present.
286 	 * Have to append to the file
287 	 */
288 	HAL_DEBUG (("\n Passed value not found. Will append to the file"));
289 	if (fseek (pfile, 0, SEEK_END) != 0) {
290 		HAL_ERROR (("\n Error in fseek to %s: %s",
291 		    POWER_CONF_FILE, strerror (errno)));
292 		res = errno;
293 		goto out;
294 	}
295 
296 	/*
297 	 * Update the file with new values
298 	 */
299 	sprintf (file_update_str, "%s %s \n", file_edit_type, file_edit_value);
300 
301 	if (fputs (file_update_str, pfile) == EOF) {
302 		HAL_ERROR (("Error in writing to file %s: %s",
303 		    POWER_CONF_FILE, strerror (errno)));
304 		res = errno;
305 		goto out;
306 	}
307 
308 	if (fflush (pfile) == EOF) {
309 		HAL_ERROR (("\n Error in flushing to %s: %s",
310 		    POWER_CONF_FILE, strerror (errno)));
311 	}
312 	res = 0;
313 out:
314 	fclose (pfile);
315 	return (res);
316 }
317 
318 /*
319  * Depending on the type(cpupm or cpu-threshold) to read, check if they are
320  * present. If present, return the corresponding value through pc_value arg
321  * and return 1 from the function. If there is no corresponding entry,return 0.
322  * Return -1 on error
323  */
324 
325 static int
326 read_power_conf_file(pconf_edit_type *pc_value,
327     power_conf_hal_type pc_hal_type)
328 {
329 
330 	FILE	*pfile;
331 	char  	tstr[FILE_ARR_SIZE];
332 	long	fset = 0;
333 	char	*file_edit_type;
334 	char	*tpstr;
335 	int	res = 0;
336 
337 	pfile = fopen (POWER_CONF_FILE, "r");
338 	if (pfile == NULL) {
339 		HAL_INFO (("\n Cannot open the file %s: %s",
340 		    POWER_CONF_FILE, strerror (errno)));
341 		return (-1);
342 	}
343 
344 	switch (pc_hal_type) {
345 	case CPU_GOV:
346 		file_edit_type = "cpupm";
347 		break;
348 	case CPU_PERFORMANCE:
349 		file_edit_type = "cpu-threshold";
350 		break;
351 	default :
352 		HAL_DEBUG (("Cannot recognize the HAL type to get value"));
353 		res = -1;
354 		goto out;
355 	}
356 
357 	while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
358 		if ((tstr == NULL) || (strlen (tstr) <= 0))
359 			continue;
360 		/*
361 		 * Look for line containing "cpupm" or "cpu-threshold"
362 		 */
363 		if (strstr (tstr, file_edit_type) == NULL)
364 			continue;
365 
366 		/*
367 		 * If the required value already present. Just
368 		 * get the value
369 		 */
370 		tpstr = strtok (tstr, " ");
371 		tpstr = strtok (NULL, " ");
372 		if (tpstr == NULL) {
373 			HAL_INFO (("Value of %s in %s is not valid",
374 			    file_edit_type, POWER_CONF_FILE));
375 			res = -1;
376 			goto out;
377 		}
378 
379 		if (pc_hal_type == CPU_GOV) {
380 			/*
381 			 * Copy the corresponding governor
382 			 */
383 			if (strcmp (tpstr, "enable") == 0) {
384 				sprintf (pc_value->cpu_gov,
385 				    "%s", "ondemand");
386 			} else {
387 				sprintf (pc_value->cpu_gov,
388 				    "%s", "performance");
389 			}
390 		} else {
391 			pc_value->cpu_th = atoi (tpstr);
392 		}
393 		res = 1;
394 		goto out;
395 	}
396 	/*
397 	 * Entry not found in the file
398 	 */
399 	HAL_DEBUG ((" No entry of %s in %s", file_edit_type, POWER_CONF_FILE));
400 	res = 0;
401 
402 out:
403 	fclose (pfile);
404 	return (res);
405 }
406 
407 
408 /*
409  * Depending on the type(Governor or Perfromance) to read, get the current
410  * values through PM ioctls().
411  * For "Governor", return the cpupm state and for "Performance" return the
412  * current cpu threshold.
413  * Return the corresponding value through cur_value and return 1 from the
414  * function for success. Return -1 on error
415  */
416 
417 static int
418 get_cur_val(pconf_edit_type *cur_value,
419     power_conf_hal_type pc_hal_type)
420 {
421 
422 	int pm_fd;
423 	int res = -1;
424 	int pm_ret;
425 
426 	pm_fd = open (PM, O_RDONLY);
427 	if (pm_fd == -1) {
428 		HAL_ERROR (("Error opening %s: %s \n", PM, strerror (errno)));
429 		return (res);
430 	}
431 
432 	switch (pc_hal_type) {
433 	case CPU_GOV:
434 		/*
435 		 * First check the PM_GET_CPUPM_STATE. If it is not available
436 		 * then check PM_GET_PM_STATE
437 		 */
438 		pm_ret = ioctl (pm_fd, PM_GET_CPUPM_STATE);
439 		if (pm_ret < 0) {
440 			HAL_ERROR (("Error in ioctl PM_GET_CPUPM_STATE: %s \n",
441 			    strerror (errno)));
442 			goto out;
443 		}
444 		switch (pm_ret) {
445 		case PM_CPU_PM_ENABLED:
446 			sprintf (cur_value->cpu_gov, "%s", "ondemand");
447 			res = 1;
448 			goto out;
449 		case PM_CPU_PM_DISABLED:
450 			sprintf (cur_value->cpu_gov, "%s", "performance");
451 			res = 1;
452 			goto out;
453 		case PM_CPU_PM_NOTSET:
454 			/*
455 			 * Check for PM_GET_PM_STATE
456 			 */
457 			pm_ret = ioctl (pm_fd, PM_GET_PM_STATE);
458 			if (pm_ret < 0) {
459 				HAL_ERROR (("Error in ioctl PM_GET_PM_STATE: "
460 				    "%s", strerror (errno)));
461 				goto out;
462 			}
463 			switch (pm_ret) {
464 			case PM_SYSTEM_PM_ENABLED:
465 				sprintf (cur_value->cpu_gov, "%s", "ondemand");
466 				res = 1;
467 				goto out;
468 			case PM_SYSTEM_PM_DISABLED:
469 				sprintf (cur_value->cpu_gov, "%s",
470 				    "performance");
471 				res = 1;
472 				goto out;
473 			default:
474 				HAL_ERROR (("PM Internal error during ioctl "
475 				    "PM_GET_PM_STATE"));
476 				goto out;
477 			}
478 		default:
479 			HAL_ERROR (("Unknown value ioctl PM_GET_CPUPM_STATE"));
480 			goto out;
481 		}
482 	case CPU_PERFORMANCE:
483 		/*
484 		 * First check the PM_GET_CPU_THRESHOLD. If it is not available
485 		 * then check PM_GET_SYSTEM_THRESHOLD
486 		 */
487 		pm_ret = ioctl (pm_fd, PM_GET_CPU_THRESHOLD);
488 		if (pm_ret >= 0) {
489 			cur_value->cpu_th = pm_ret;
490 			res = 1;
491 			goto out;
492 		} else if ((pm_ret == EINVAL) || (pm_ret == ENOTTY)) {
493 			/*
494 			 * PM_GET_CPU_THRESHOLD is not available
495 			 */
496 			pm_ret = ioctl (pm_fd, PM_GET_SYSTEM_THRESHOLD);
497 			if (res >= 0) {
498 				cur_value->cpu_th = pm_ret;
499 				res = 1;
500 				goto out;
501 			} else {
502 				HAL_ERROR (("Error in PM_GET_CPU_THRESHOLD: %s",
503 				    strerror (errno)));
504 				goto out;
505 			}
506 		} else {
507 			HAL_ERROR ((" Error in ioctl PM_GET_CPU_THRESHOLD: %s",
508 			    strerror (errno)));
509 			goto out;
510 		}
511 	default :
512 		HAL_DEBUG (("Cannot recognize the HAL type to get value"));
513 		goto out;
514 	}
515 out:
516 	close (pm_fd);
517 	return (res);
518 }
519 /*
520  * Send an error message as a response to the pending call
521  */
522 static void
523 generate_err_msg(DBusConnection *con,
524     DBusMessage *msg,
525     const char *err_name,
526     char *fmt, ...)
527 {
528 
529 	DBusMessage	*err_msg;
530 	char		err_buf[ERR_BUF_SIZE];
531 	va_list		va_args;
532 
533 	va_start (va_args, fmt);
534 	vsnprintf (err_buf, ERR_BUF_SIZE, fmt, va_args);
535 	va_end (va_args);
536 
537 	HAL_DEBUG ((" Sending error message: %s", err_buf));
538 
539 	err_msg = dbus_message_new_error (msg, err_name, err_buf);
540 	if (err_msg == NULL) {
541 		HAL_ERROR (("No Memory for DBUS error msg"));
542 		return;
543 	}
544 
545 	if (!dbus_connection_send (con, err_msg, NULL)) {
546 		HAL_ERROR ((" Out Of Memory!"));
547 	}
548 	dbus_connection_flush (con);
549 
550 }
551 
552 static void
553 gen_unknown_gov_err(DBusConnection *con,
554     DBusMessage *msg,
555     char *err_str)
556 {
557 
558 	generate_err_msg (con,
559 	    msg,
560 	    "org.freedesktop.Hal.CPUFreq.UnknownGovernor",
561 	    "Unknown CPUFreq Governor: %s",
562 	    err_str);
563 }
564 
565 static void
566 gen_no_suitable_gov_err(DBusConnection *con,
567     DBusMessage *msg,
568     char *err_str)
569 {
570 
571 	generate_err_msg (con,
572 	    msg,
573 	    "org.freedesktop.Hal.CPUFreq.NoSuitableGovernor",
574 	    "Could not find a suitable governor: %s",
575 	    err_str);
576 }
577 
578 static void
579 gen_cpufreq_err(DBusConnection *con,
580     DBusMessage *msg,
581     char *err_str)
582 {
583 	generate_err_msg (con,
584 	    msg,
585 	    "org.freedesktop.Hal.CPUFreq.Error",
586 	    "%s: Syslog might give more information",
587 	    err_str);
588 }
589 
590 
591 /*
592  * Puts the required cpufreq audit data and calls adt_put_event()
593  * to generate auditing
594  */
595 static void
596 audit_cpufreq(const adt_export_data_t *imported_state, au_event_t event_id,
597     int result, const char *auth_used, const int cpu_thr_value)
598 {
599 	adt_session_data_t	*ah;
600 	adt_event_data_t	*event;
601 	struct passwd		*msg_pwd;
602 	uid_t			gid;
603 
604 	if (adt_start_session (&ah, imported_state, 0) != 0) {
605 		HAL_INFO (("adt_start_session failed: %s", strerror (errno)));
606 		return;
607 	}
608 
609 	if ((event = adt_alloc_event (ah, event_id)) == NULL) {
610 		HAL_INFO(("adt_alloc_event audit_cpufreq failed: %s",
611 		    strerror (errno)));
612 		return;
613 	}
614 
615 	switch (event_id) {
616 	case ADT_cpu_ondemand:
617 		event->adt_cpu_ondemand.auth_used = (char *)auth_used;
618 		break;
619 	case ADT_cpu_performance:
620 		event->adt_cpu_performance.auth_used = (char *)auth_used;
621 		break;
622 	case ADT_cpu_threshold:
623 		event->adt_cpu_threshold.auth_used = (char *)auth_used;
624 		event->adt_cpu_threshold.threshold = cpu_thr_value;
625 		break;
626 	default:
627 		goto clean;
628 	}
629 
630 	if (result == 0) {
631 		if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
632 			HAL_INFO (("adt_put_event(%d, ADT_SUCCESS) failed",
633 			    event_id));
634 		}
635 	} else {
636 		if (adt_put_event (event, ADT_FAILURE, result) != 0) {
637 			HAL_INFO (("adt_put_event(%d, ADT_FAILURE) failed",
638 			    event_id));
639 		}
640 	}
641 
642 clean:
643 	adt_free_event (event);
644 	(void) adt_end_session (ah);
645 }
646 
647 /*
648  * Check if the cpufreq related operations are authorized
649  */
650 
651 static int
652 check_authorization(DBusConnection *con, DBusMessage *msg)
653 {
654 	int		adt_res = 0;
655 #ifdef HAVE_POLKIT
656 	char		user_id[128];
657 	char		*udi;
658 	char		*privilege;
659 	DBusError	error;
660 	gboolean	is_priv_allowed;
661 	gboolean	is_priv_temporary;
662 	DBusConnection	*system_bus = NULL;
663 	LibPolKitContext *pol_ctx = NULL;
664 
665 	/*
666 	 * Check for authorization before proceeding
667 	 */
668 	udi = getenv ("HAL_PROP_INFO_UDI");
669 	privilege = "hal-power-cpu";
670 
671 	dbus_error_init (&error);
672 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
673 	if (system_bus == NULL) {
674 		HAL_INFO (("Cannot connect to the system bus"));
675 		LIBHAL_FREE_DBUS_ERROR (&error);
676 		gen_cpufreq_err (con, msg, "Cannot connect to the system bus");
677 		adt_res = EINVAL;
678 		goto out;
679 	}
680 
681 	sender = dbus_message_get_sender (msg);
682 	HAL_INFO (("Auth Sender: %s", sender));
683 
684 	if (sender == NULL) {
685 		HAL_INFO (("Could not get the sender of the message"));
686 		gen_cpufreq_err (con, msg,
687 		    "Could not get the sender of the message");
688 		adt_res = ADT_FAIL_VALUE_AUTH;
689 		goto out;
690 	}
691 
692 	dbus_error_init (&error);
693 	uid = dbus_bus_get_unix_user (system_bus, sender, &error);
694 	if (dbus_error_is_set (&error)) {
695 		HAL_INFO (("Could not get the user id of the message"));
696 		LIBHAL_FREE_DBUS_ERROR (&error);
697 		gen_cpufreq_err (con, msg,
698 		    "Could not get the user id of the message sender");
699 		adt_res = ADT_FAIL_VALUE_AUTH;
700 		goto out;
701 	}
702 
703 	snprintf (user_id, sizeof (user_id), "%d", uid);
704 	HAL_DEBUG ((" User id is : %d", uid));
705 
706 	pol_ctx = libpolkit_new_context (system_bus);
707 	if (pol_ctx == NULL) {
708 		HAL_INFO (("Cannot get libpolkit context"));
709 		gen_cpufreq_err (con, msg,
710 		    "Cannot get libpolkit context to check privileges");
711 		adt_res = ADT_FAIL_VALUE_AUTH;
712 		goto out;
713 	}
714 
715 	if (libpolkit_is_uid_allowed_for_privilege (pol_ctx,
716 	    NULL,
717 	    user_id,
718 	    privilege,
719 	    udi,
720 	    &is_priv_allowed,
721 	    &is_priv_temporary,
722 	    NULL) != LIBPOLKIT_RESULT_OK) {
723 		HAL_INFO (("Cannot lookup privilege from PolicyKit"));
724 		gen_cpufreq_err (con, msg,
725 		    "Error looking up privileges from Policykit");
726 		adt_res = ADT_FAIL_VALUE_AUTH;
727 		goto out;
728 	}
729 
730 	if (!is_priv_allowed) {
731 		HAL_INFO (("Caller doesn't possess required privilege to"
732 		    " change the governor"));
733 		gen_cpufreq_err (con, msg,
734 		    "Caller doesn't possess required "
735 		    "privilege to change the governor");
736 		adt_res = ADT_FAIL_VALUE_AUTH;
737 		goto out;
738 	}
739 
740 	HAL_DEBUG ((" Privilege Succeed"));
741 
742 #endif
743 out:
744 	return (adt_res);
745 }
746 
747 /*
748  * Sets the CPU Freq governor. It sets the gov name in the /etc/power.conf
749  * and executes pmconfig. If governor is "ondemand" then "cpupm" is enabled in
750  * and if governor is performance, then "cpupm" is disabled
751  */
752 static void
753 set_cpufreq_gov(DBusConnection *con, DBusMessage *msg, void *udata)
754 {
755 	DBusMessageIter arg_iter;
756 	DBusMessage	*msg_reply;
757 	char		*arg_val;
758 	int		arg_type;
759 	int		pid;
760 	int		done_flag = 0;
761 	int		sleep_time = 0;
762 	int		status;
763 	int		adt_res = 0;
764 	char		tmp_conf_file[64] = "/tmp/power.conf.XXXXXX";
765 	int		tmp_fd;
766 	char		pmconfig_cmd[128];
767 	pconf_edit_type pc_edit_type;
768 #ifdef sun
769 	adt_export_data_t *adt_data;
770 	size_t 		adt_data_size;
771 	DBusConnection 	*system_bus = NULL;
772 	DBusError 	error;
773 #endif
774 
775 	if (! dbus_message_iter_init (msg, &arg_iter)) {
776 		HAL_DEBUG (("Incoming message has no arguments"));
777 		gen_unknown_gov_err (con, msg, "No governor specified");
778 		adt_res = EINVAL;
779 		goto out;
780 	}
781 	arg_type = dbus_message_iter_get_arg_type (&arg_iter);
782 
783 	if (arg_type != DBUS_TYPE_STRING) {
784 		HAL_DEBUG (("Incomming message arg type is not string"));
785 		gen_unknown_gov_err (con, msg,
786 		    "Specified governor is not a string");
787 		adt_res = EINVAL;
788 		goto out;
789 	}
790 	dbus_message_iter_get_basic (&arg_iter, &arg_val);
791 	if (arg_val != NULL) {
792 		HAL_DEBUG (("SetCPUFreqGov is: %s", arg_val));
793 	} else {
794 		HAL_DEBUG (("Could not get SetCPUFreqGov from message iter"));
795 		adt_res = EINVAL;
796 		goto out;
797 	}
798 
799 	adt_res = check_authorization (con, msg);
800 
801 	if (adt_res != 0) {
802 		goto out;
803 	}
804 
805 	/*
806 	 * Update the /etc/power.conf file.
807 	 */
808 	tmp_fd = mkstemp (tmp_conf_file);
809 	if (tmp_fd == -1) {
810 		HAL_ERROR ((" Error in creating a temp conf file"));
811 		adt_res = EINVAL;
812 		goto out;
813 	}
814 	strcpy (pc_edit_type.cpu_gov, arg_val);
815 	adt_res = edit_power_conf_file (pc_edit_type, CPU_GOV, tmp_conf_file);
816 	if (adt_res != 0) {
817 		HAL_DEBUG (("Error in edit /etc/power.conf"));
818 		gen_cpufreq_err (con, msg,
819 		    "Internal Error while setting the governor");
820 		unlink (tmp_conf_file);
821 		goto out;
822 	}
823 
824 	/*
825 	 * Execute pmconfig
826 	 */
827 	sprintf (pmconfig_cmd, "%s %s", PMCONFIG, tmp_conf_file);
828 	if (system (pmconfig_cmd) != 0) {
829 		HAL_ERROR ((" Error in executing pmconfig: %s",
830 		    strerror (errno)));
831 		adt_res = errno;
832 		gen_cpufreq_err (con, msg, "Error in executing pmconfig");
833 		unlink (tmp_conf_file);
834 		goto out;
835 	}
836 	unlink (tmp_conf_file);
837 	HAL_DEBUG (("Executed pmconfig"));
838 	sprintf (current_gov, "%s", arg_val);
839 
840 	/*
841 	 * Just return an empty response, so that if the client
842 	 * is waiting for any response will not keep waiting
843 	 */
844 	msg_reply = dbus_message_new_method_return (msg);
845 	if (msg_reply == NULL) {
846 		HAL_ERROR (("Out of memory to msg reply"));
847 		gen_cpufreq_err (con, msg,
848 		    "Out of memory to create a response");
849 		adt_res = ENOMEM;
850 		goto out;
851 	}
852 
853 	if (!dbus_connection_send (con, msg_reply, NULL)) {
854 		HAL_ERROR (("Out of memory to msg reply"));
855 		gen_cpufreq_err (con, msg,
856 		    "Out of memory to create a response");
857 		adt_res = ENOMEM;
858 		goto out;
859 	}
860 
861 	dbus_connection_flush (con);
862 
863 out:
864 
865 #ifdef sun
866 	/*
867 	 * Audit the new governor change
868 	 */
869 	dbus_error_init (&error);
870 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
871 	if (system_bus == NULL) {
872 		HAL_INFO (("Cannot connect to the system bus %s",
873 		    error.message));
874 		LIBHAL_FREE_DBUS_ERROR (&error);
875 		return;
876 	}
877 
878 	adt_data = get_audit_export_data (system_bus, sender, &adt_data_size);
879 	if (adt_data != NULL) {
880 		if (strcmp (arg_val, "ondemand") == 0) {
881 			audit_cpufreq (adt_data, ADT_cpu_ondemand, adt_res,
882 			    "solaris.system.power.cpu", 0);
883 		} else if (strcmp (arg_val, "performance") == 0) {
884 			audit_cpufreq (adt_data, ADT_cpu_performance, adt_res,
885 			    "solaris.system.power.cpu", 0);
886 		}
887 		free (adt_data);
888 	} else {
889 		HAL_INFO ((" Could not get audit export data"));
890 	}
891 #endif /* sun */
892 }
893 
894 /*
895  * Sets the CPU Freq performance. It sets the cpu-threshold in the
896  * /etc/power.conf and executes pmconfig. The performnace value should
897  * be between 1 to 100. The cpu-threshold = ((performance val) * 15) secs.
898  */
899 static void
900 set_cpufreq_performance(DBusConnection *con, DBusMessage *msg, void *udata)
901 {
902 
903 	DBusMessageIter arg_iter;
904 	DBusMessage	*msg_reply;
905 	int		arg_val;
906 	int		arg_type;
907 	int		pid;
908 	int		done_flag = 0;
909 	int		sleep_time = 0;
910 	int		adt_res = 0;
911 	char		tmp_conf_file[64] = "/tmp/power.conf.XXXXXX";
912 	int		tmp_fd;
913 	char		pmconfig_cmd[128];
914 	pconf_edit_type pc_edit_type;
915 #ifdef sun
916 	adt_export_data_t *adt_data;
917 	size_t 		adt_data_size;
918 	DBusConnection 	*system_bus = NULL;
919 	DBusError 	error;
920 #endif
921 
922 	adt_res = check_authorization (con, msg);
923 
924 	if (adt_res != 0) {
925 		goto out;
926 	}
927 
928 	/*
929 	 * Performance can only be set to dynamic governors. Currently the
930 	 * only supported dynamic governor is ondemand.
931 	 */
932 	if (current_gov[0] == 0) {
933 		/*
934 		 * Read the current governor from /etc/power.conf
935 		 */
936 		if (read_power_conf_file (&pc_edit_type, CPU_GOV) != 1) {
937 			HAL_ERROR ((" Error in reading from /etc/power.conf"));
938 			gen_cpufreq_err (con, msg, "Internal error while "
939 			    "getting the governor");
940 			adt_res = EINVAL;
941 			goto out;
942 		}
943 		sprintf (current_gov, "%s", pc_edit_type.cpu_gov);
944 	}
945 
946 	if (strcmp (current_gov, "ondemand") != 0) {
947 		HAL_DEBUG (("To set performance the current gov should be "
948 		    "dynamic like ondemand"));
949 		gen_no_suitable_gov_err (con, msg, "Cannot set performance "
950 		    "to the current governor");
951 		adt_res = EINVAL;
952 		goto out;
953 	}
954 
955 	if (! dbus_message_iter_init (msg, &arg_iter)) {
956 		HAL_DEBUG (("Incoming message has no arguments"));
957 		gen_no_suitable_gov_err(con, msg, "No performance specified");
958 		adt_res = EINVAL;
959 		goto out;
960 	}
961 	arg_type = dbus_message_iter_get_arg_type (&arg_iter);
962 
963 	if (arg_type != DBUS_TYPE_INT32) {
964 		HAL_DEBUG (("Incomming message arg type is not Integer"));
965 		gen_no_suitable_gov_err (con, msg,
966 		    "Specified performance is not a Integer");
967 		adt_res = EINVAL;
968 		goto out;
969 	}
970 	dbus_message_iter_get_basic (&arg_iter, &arg_val);
971 	if ((arg_val < 1) || (arg_val > 100)) {
972 		HAL_INFO (("SetCPUFreqPerformance should be between 1 to 100"
973 		    ": %d", arg_val));
974 		gen_no_suitable_gov_err (con, msg,
975 		    "Performance value should be between 1 and 100");
976 		adt_res = EINVAL;
977 		goto out;
978 	}
979 
980 	HAL_DEBUG (("SetCPUFreqPerformance is: %d", arg_val));
981 
982 	/*
983 	 * Update the /etc/power.conf file
984 	 */
985 	tmp_fd = mkstemp (tmp_conf_file);
986 	if (tmp_fd == -1) {
987 		HAL_ERROR ((" Error in creating a temp conf file"));
988 		adt_res = EINVAL;
989 		goto out;
990 	}
991 	pc_edit_type.cpu_th = arg_val * 15;
992 	adt_res = edit_power_conf_file (pc_edit_type, CPU_PERFORMANCE,
993 	    tmp_conf_file);
994 	if (adt_res != 0) {
995 		HAL_DEBUG (("Error while editing /etc/power.conf"));
996 		gen_cpufreq_err (con, msg,
997 		    "Internal error while setting the performance");
998 		unlink (tmp_conf_file);
999 		goto out;
1000 	}
1001 
1002 	/*
1003 	 * Execute pmconfig
1004 	 */
1005 	sprintf (pmconfig_cmd, "%s %s", PMCONFIG, tmp_conf_file);
1006 	if (system (pmconfig_cmd) != 0) {
1007 		HAL_ERROR ((" Error in executing pmconfig: %s",
1008 		    strerror (errno)));
1009 		adt_res = errno;
1010 		gen_cpufreq_err (con, msg,
1011 		    "Internal error while setting the performance");
1012 		unlink (tmp_conf_file);
1013 		goto out;
1014 	}
1015 	unlink (tmp_conf_file);
1016 	HAL_DEBUG (("Executed pmconfig"));
1017 
1018 	/*
1019 	 * Just return an empty response, so that if the client
1020 	 * is waiting for any response will not keep waiting
1021 	 */
1022 
1023 	msg_reply = dbus_message_new_method_return (msg);
1024 	if (msg_reply == NULL) {
1025 		HAL_ERROR (("Out of memory to msg reply"));
1026 		gen_cpufreq_err (con, msg,
1027 		    "Out of memory to create a response");
1028 		adt_res = ENOMEM;
1029 		goto out;
1030 	}
1031 
1032 	if (!dbus_connection_send (con, msg_reply, NULL)) {
1033 		HAL_ERROR (("Out of memory to msg reply"));
1034 		gen_cpufreq_err (con, msg,
1035 		    "Out of memory to create a response");
1036 		adt_res = ENOMEM;
1037 		goto out;
1038 	}
1039 
1040 	dbus_connection_flush (con);
1041 out:
1042 #ifdef sun
1043 
1044 	/*
1045 	 * Audit the new performance change
1046 	 */
1047 	dbus_error_init (&error);
1048 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
1049 	if (system_bus == NULL) {
1050 		HAL_INFO (("Cannot connect to the system bus %s",
1051 		    error.message));
1052 		LIBHAL_FREE_DBUS_ERROR (&error);
1053 		return;
1054 	}
1055 
1056 	adt_data = get_audit_export_data (system_bus, sender, &adt_data_size);
1057 	if (adt_data != NULL) {
1058 		audit_cpufreq (adt_data, ADT_cpu_threshold, adt_res,
1059 		    "solaris.system.power.cpu", arg_val);
1060 		free (adt_data);
1061 	} else {
1062 		HAL_INFO ((" Could not get audit export data"));
1063 	}
1064 
1065 #endif /* sun */
1066 }
1067 
1068 /*
1069  * Returns in the dbus message the current gov.
1070  */
1071 static void
1072 get_cpufreq_gov(DBusConnection *con, DBusMessage *msg, void *udata)
1073 {
1074 
1075 	DBusMessageIter rep_iter;
1076 	DBusMessage	*msg_reply;
1077 	int 		res;
1078 	pconf_edit_type pc_type;
1079 	char		*param;
1080 
1081 	/*
1082 	 * Get the governor type from /etc/power.conf if it is present.
1083 	 */
1084 	res = get_cur_val (&pc_type, CPU_GOV);
1085 	if (res != 1) {
1086 		HAL_INFO ((" Error in getting the current governor"));
1087 		gen_cpufreq_err (con, msg, "Internal error while getting"
1088 		    " the governor");
1089 		return;
1090 	}
1091 
1092 	HAL_DEBUG ((" Current governor is: %s", pc_type.cpu_gov));
1093 
1094 	msg_reply = dbus_message_new_method_return (msg);
1095 	if (msg_reply == NULL) {
1096 		HAL_ERROR (("Out of memory to msg reply"));
1097 		gen_cpufreq_err (con, msg,
1098 		    "Internal error while getting the governor");
1099 		return;
1100 	}
1101 
1102 	/*
1103 	 * Append reply arguments
1104 	 */
1105 	param = (char *) malloc (sizeof (char) * 250);
1106 	if (param == NULL) {
1107 		HAL_ERROR (("\n Could not allocate mem to param"));
1108 		gen_cpufreq_err (con, msg, "Internal error while getting"
1109 		    " the governor");
1110 		return;
1111 	}
1112 	sprintf (param, "%s",  pc_type.cpu_gov);
1113 
1114 	dbus_message_iter_init_append (msg_reply, &rep_iter);
1115 	if (!dbus_message_iter_append_basic (&rep_iter, DBUS_TYPE_STRING,
1116 	    &param)) {
1117 		HAL_ERROR (("\n Out Of Memory!\n"));
1118 		gen_cpufreq_err (con, msg, "Internal error while getting"
1119 		    " the governor");
1120 		free (param);
1121 		return;
1122 	}
1123 
1124 	if (!dbus_connection_send (con, msg_reply, NULL)) {
1125 		HAL_ERROR (("\n Out Of Memory!\n"));
1126 		gen_cpufreq_err (con, msg, "Internal error while getting"
1127 		    " the governor");
1128 		free (param);
1129 		return;
1130 	}
1131 	dbus_connection_flush (con);
1132 	free (param);
1133 }
1134 
1135 /*
1136  * Returns in the dbus message the current performance value
1137  */
1138 static void
1139 get_cpufreq_performance(DBusConnection *con, DBusMessage *msg, void *udata)
1140 {
1141 
1142 	DBusMessageIter rep_iter;
1143 	DBusMessage	*msg_reply;
1144 	int 		res;
1145 	pconf_edit_type pc_type;
1146 	int		param_int;
1147 
1148 	/*
1149 	 * Get the performance value
1150 	 */
1151 	res = get_cur_val (&pc_type, CPU_PERFORMANCE);
1152 	if (res != 1) {
1153 		HAL_INFO ((" Error in getting current performance"));
1154 		gen_cpufreq_err (con, msg, "Internal error while getting"
1155 		    " the performance value");
1156 		return;
1157 	}
1158 
1159 	HAL_DEBUG ((" The current performance: %d", pc_type.cpu_th));
1160 
1161 	msg_reply = dbus_message_new_method_return (msg);
1162 	if (msg_reply == NULL) {
1163 		HAL_ERROR (("Out of memory to msg reply"));
1164 		gen_cpufreq_err (con, msg, "Internal error while getting"
1165 		    " the performance value");
1166 		return;
1167 	}
1168 
1169 	/*
1170 	 * Append reply arguments.pc_type.cpu_th gives the current cputhreshold
1171 	 * vlaue in seconds. Have to convert it into CPU HAL interface
1172 	 * performance value
1173 	 */
1174 	if (pc_type.cpu_th < 15)
1175 		param_int = 1;
1176 	else
1177 		param_int = (pc_type.cpu_th / 15);
1178 
1179 	HAL_DEBUG (("Performance: %d \n", param_int));
1180 
1181 	dbus_message_iter_init_append (msg_reply, &rep_iter);
1182 	if (!dbus_message_iter_append_basic (&rep_iter, DBUS_TYPE_INT32,
1183 	    &param_int)) {
1184 		HAL_ERROR (("\n Out Of Memory!\n"));
1185 		gen_cpufreq_err (con, msg, "Internal error while getting"
1186 		    " the performance value");
1187 		return;
1188 	}
1189 
1190 	if (!dbus_connection_send (con, msg_reply, NULL)) {
1191 		HAL_ERROR (("\n Out Of Memory!\n"));
1192 		gen_cpufreq_err (con, msg, "Internal error while getting"
1193 		    " the performance value");
1194 		return;
1195 	}
1196 	dbus_connection_flush (con);
1197 }
1198 
1199 /*
1200  * Returns list of available governors. Currently just two governors are
1201  * supported. They are "ondemand" and "performance"
1202  */
1203 
1204 static void
1205 get_cpufreq_avail_gov(DBusConnection *con, DBusMessage *msg, void *udata)
1206 {
1207 
1208 	DBusMessageIter rep_iter;
1209 	DBusMessageIter array_iter;
1210 	DBusMessage	*msg_reply;
1211 	int		ngov;
1212 
1213 	msg_reply = dbus_message_new_method_return (msg);
1214 	if (msg_reply == NULL) {
1215 		HAL_ERROR (("Out of memory to msg reply"));
1216 		gen_cpufreq_err (con, msg, "Internal error while getting"
1217 		    " the list of governors");
1218 		return;
1219 	}
1220 
1221 	/*
1222 	 * Append reply arguments
1223 	 */
1224 	dbus_message_iter_init_append (msg_reply, &rep_iter);
1225 
1226 	if (!dbus_message_iter_open_container (&rep_iter,
1227 	    DBUS_TYPE_ARRAY,
1228 	    DBUS_TYPE_STRING_AS_STRING,
1229 	    &array_iter)) {
1230 		HAL_ERROR (("\n Out of memory to msg reply array"));
1231 		gen_cpufreq_err (con, msg, "Internal error while getting"
1232 		    " the list of governors");
1233 		return;
1234 	}
1235 
1236 	for (ngov = 0; gov_list[ngov] != NULL; ngov++) {
1237 		if (gov_list[ngov])
1238 			HAL_DEBUG (("\n%d Gov Name: %s", ngov, gov_list[ngov]));
1239 			dbus_message_iter_append_basic (&array_iter,
1240 			    DBUS_TYPE_STRING,
1241 			    &gov_list[ngov]);
1242 	}
1243 	dbus_message_iter_close_container (&rep_iter, &array_iter);
1244 
1245 	if (!dbus_connection_send (con, msg_reply, NULL)) {
1246 		HAL_ERROR (("\n Out Of Memory!\n"));
1247 		gen_cpufreq_err (con, msg, "Internal error while getting"
1248 		    " the list of governors");
1249 		return;
1250 	}
1251 	dbus_connection_flush (con);
1252 }
1253 
1254 static DBusHandlerResult
1255 hald_dbus_cpufreq_filter(DBusConnection *con, DBusMessage *msg, void *udata)
1256 {
1257 	HAL_DEBUG ((" Inside CPUFreq filter:%s", dbus_message_get_path(msg)));
1258 	/*
1259 	 * Check for method types
1260 	 */
1261 	if (!dbus_connection_get_is_connected (con))
1262 		HAL_DEBUG (("Connection disconnected in cpufreq addon"));
1263 
1264 	if (dbus_message_is_method_call (msg,
1265 	    "org.freedesktop.Hal.Device.CPUFreq",
1266 	    "SetCPUFreqGovernor")) {
1267 		HAL_DEBUG (("---- SetCPUFreqGovernor is called "));
1268 
1269 		set_cpufreq_gov (con, msg, udata);
1270 
1271 	} else if (dbus_message_is_method_call (msg,
1272 	    "org.freedesktop.Hal.Device.CPUFreq",
1273 	    "GetCPUFreqGovernor")) {
1274 		HAL_DEBUG (("---- GetCPUFreqGovernor is called "));
1275 
1276 		get_cpufreq_gov (con, msg, udata);
1277 	} else if (dbus_message_is_method_call (msg,
1278 	    "org.freedesktop.Hal.Device.CPUFreq",
1279 	    "GetCPUFreqAvailableGovernors")) {
1280 		HAL_DEBUG (("---- GetCPUFreqAvailableGovernors is called "));
1281 
1282 		get_cpufreq_avail_gov (con, msg, udata);
1283 	} else if (dbus_message_is_method_call (msg,
1284 	    "org.freedesktop.Hal.Device.CPUFreq",
1285 	    "SetCPUFreqPerformance")) {
1286 		HAL_DEBUG (("---- SetCPUFreqPerformance is called "));
1287 
1288 		set_cpufreq_performance (con, msg, udata);
1289 	} else if (dbus_message_is_method_call (msg,
1290 	    "org.freedesktop.Hal.Device.CPUFreq",
1291 	    "GetCPUFreqPerformance")) {
1292 		HAL_DEBUG (("---- GetCPUFreqPerformance is called "));
1293 
1294 		get_cpufreq_performance (con, msg, udata);
1295 	} else {
1296 		HAL_DEBUG (("---Not Set/Get cpufreq gov---"));
1297 	}
1298 
1299 	return (DBUS_HANDLER_RESULT_HANDLED);
1300 
1301 }
1302 
1303 static void
1304 drop_privileges()
1305 {
1306 	priv_set_t *pPrivSet = NULL;
1307 	priv_set_t *lPrivSet = NULL;
1308 
1309 	/*
1310 	 * Start with the 'basic' privilege set and then add any
1311 	 * of the privileges that will be required.
1312 	 */
1313 	if ((pPrivSet = priv_str_to_set ("basic", ",", NULL)) == NULL) {
1314 		HAL_INFO (("Error in setting the priv"));
1315 		return;
1316 	}
1317 
1318 	(void) priv_addset (pPrivSet, PRIV_SYS_DEVICES);
1319 
1320 	if (setppriv (PRIV_SET, PRIV_INHERITABLE, pPrivSet) != 0) {
1321 		HAL_INFO (("Could not set the privileges"));
1322 		priv_freeset (pPrivSet);
1323 		return;
1324 	}
1325 
1326 	(void) priv_addset (pPrivSet, PRIV_PROC_AUDIT);
1327 	(void) priv_addset (pPrivSet, PRIV_SYS_CONFIG);
1328 
1329 	if (setppriv (PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
1330 		HAL_INFO (("Could not set the privileges"));
1331 		priv_freeset (pPrivSet);
1332 		return;
1333 	}
1334 
1335 	priv_freeset (pPrivSet);
1336 
1337 }
1338 
1339 int
1340 main(int argc, char **argv)
1341 {
1342 
1343 	LibHalContext *ctx = NULL;
1344 	char *udi;
1345 	DBusError error;
1346 	DBusConnection *conn;
1347 
1348 	GMainLoop *loop = g_main_loop_new (NULL, FALSE);
1349 
1350 	drop_privileges ();
1351 	openlog ("hald-addon-cpufreq", LOG_PID, LOG_DAEMON);
1352 	setup_logger ();
1353 
1354 	bzero (current_gov, EDIT_TYPE_SIZE-1);
1355 
1356 	if ((udi = getenv ("UDI")) == NULL) {
1357 		HAL_INFO (("\n Could not get the UDI in addon-cpufreq"));
1358 		return (0);
1359 	}
1360 
1361 	dbus_error_init (&error);
1362 	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
1363 		HAL_ERROR (("main(): init_direct failed\n"));
1364 		return (0);
1365 	}
1366 	dbus_error_init (&error);
1367 	if (!libhal_device_addon_is_ready (ctx, getenv ("UDI"), &error)) {
1368 		check_and_free_error (&error);
1369 		return (0);
1370 	}
1371 
1372 	/*
1373 	 * Claim the cpufreq interface
1374 	 */
1375 
1376 	HAL_DEBUG (("cpufreq Introspect XML: %s", cpufreq_introspect_xml));
1377 
1378 	if (!libhal_device_claim_interface (ctx,
1379 	    udi,
1380 	    "org.freedesktop.Hal.Device.CPUFreq",
1381 	    cpufreq_introspect_xml,
1382 	    &error)) {
1383 		HAL_DEBUG ((" Cannot claim the CPUFreq interface"));
1384 		check_and_free_error (&error);
1385 		return (0);
1386 	}
1387 
1388 	conn = libhal_ctx_get_dbus_connection (ctx);
1389 
1390 	/*
1391 	 * Add the cpufreq capability
1392 	 */
1393 	if (!libhal_device_add_capability (ctx,
1394 	    udi,
1395 	    "cpufreq_control",
1396 	    &error)) {
1397 		HAL_DEBUG ((" Could not add cpufreq_control capability"));
1398 		check_and_free_error (&error);
1399 		return (0);
1400 	}
1401 	/*
1402 	 * Watches and times incoming messages
1403 	 */
1404 
1405 	dbus_connection_setup_with_g_main (conn, NULL);
1406 
1407 	/*
1408 	 * Add a filter function which gets called when a message comes in
1409 	 * and processes the message
1410 	 */
1411 
1412 	if (!dbus_connection_add_filter (conn,
1413 	    hald_dbus_cpufreq_filter,
1414 	    NULL,
1415 	    NULL)) {
1416 		HAL_INFO ((" Cannot add the CPUFreq filter function"));
1417 		return (0);
1418 	}
1419 
1420 	dbus_connection_set_exit_on_disconnect (conn, 0);
1421 
1422 	g_main_loop_run (loop);
1423 }
1424