DaemonForums  

Go Back   DaemonForums > Miscellaneous > Programming

Programming C, bash, Python, Perl, PHP, Java, you name it.

Reply
 
Thread Tools Display Modes
  #1   (View Single Post)  
Old 11th January 2009
Carpetsmoker's Avatar
Carpetsmoker Carpetsmoker is offline
Real Name: Martin
Tcpdump Spy
 
Join Date: Apr 2008
Location: Netherlands
Posts: 2,243
Default sysctlbyname() On FreeBSD

I recently bought a Thinkpad T61 (Didn't go for the Dell Vermaden), but all battery indicators I could find for FreeBSD eiter do not work, or don't work as I want them to, creating a simple tray application is simple, but I'm having problems with getting the sysctl.

From the commandline:
% sysctl hw.acpi.battery.life
hw.acpi.battery.life: 99


99% means its full, so now from python, from an example found here:

Code:
def CheckBatt(tray):
        libc = ctypes.CDLL('libc.so')
        size = ctypes.c_uint(0)
        #libc.sysctlbyname("hw.acpi.battery.life", None, ctypes.byref(size), None, 0) 
        buf = ctypes.create_string_buffer(size.value)
        libc.sysctlbyname("hw.acpi.battery.life", buf, ctypes.byref(size), None, 0)

        print buf.value
        return True
output: `c'

Hm, maybe something went wrong with ctypes? Lets try from C:

Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysctl.h>

int
main()
{
        size_t size;
        int buf;
        size = sizeof buf;

        sysctlbyname("hw.acpi.battery.life", &buf, &size, NULL, 0);

        printf("`%s'\n", &buf);
        return 0;
}
Output: `c' ... So the problem isn't in ctypes, but probably in my use of sysctlbyname() (?)

I am not an experienced C programmer, I usually stick to stuff like python, I'm probably doing something stupid, but I can't figure out what.

Also, why does the python example linked above use two sysctlbyname() calls? It seems redundant to me...
__________________
UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things.
Reply With Quote
  #2   (View Single Post)  
Old 11th January 2009
anemos's Avatar
anemos anemos is offline
Fdisk Soldier
 
Join Date: May 2008
Location: Ελλάδα
Posts: 53
Default

I think you have to write
Code:
printf("`%d'\n", buf);
instead of
Code:
printf("`%s'\n", &buf);
Reply With Quote
  #3   (View Single Post)  
Old 11th January 2009
ephemera's Avatar
ephemera ephemera is offline
Knuth's homeboy
 
Join Date: Apr 2008
Posts: 537
Default

try:
Code:
        if (sysctlbyname("hw.acpi.battery.life", &buf, &size, NULL, 0) < 0) {
             perror("sysctl"); 
             exit(1); 
       }

        printf("`%d'\n", buf);
Reply With Quote
  #4   (View Single Post)  
Old 11th January 2009
Carpetsmoker's Avatar
Carpetsmoker Carpetsmoker is offline
Real Name: Martin
Tcpdump Spy
 
Join Date: Apr 2008
Location: Netherlands
Posts: 2,243
Default

No error, sysctlbyname() returns 0 as it should.
__________________
UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things.
Reply With Quote
  #5   (View Single Post)  
Old 11th January 2009
BSDfan666 BSDfan666 is offline
Real Name: N/A, this is the interweb.
Banned
 
Join Date: Apr 2008
Location: Ontario, Canada
Posts: 2,223
Default

What about the following?

Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysctl.h>

int main(void) {
	int mib[4];
	size_t len;
	char buf[BUFSIZ];
	int buflen = BUFSIZ;

	len = sizeof(mib);

	if(sysctlnametomib("hw.acpi.battery.life", mib, &len) == -1) {
		return 1;
	}

	if(sysctl(mib, len, buf, &buflen, NULL, 0) == -1) {
		return 1;
	}
	
	printf("%s\n", buf);
}
I can't confirm it'll compile, OpenBSD lacks this function..
Reply With Quote
  #6   (View Single Post)  
Old 11th January 2009
BSDfan666 BSDfan666 is offline
Real Name: N/A, this is the interweb.
Banned
 
Join Date: Apr 2008
Location: Ontario, Canada
Posts: 2,223
Default

Let's try that again...

Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysctl.h>

int main(void) {
	int mib[4], life;
	size_t miblen, lifelen;

	miblen = sizeof(mib);
	lifelen = sizeof(life);

	if(sysctlnametomib("hw.acpi.battery.life", mib, &miblen) == -1) {
		return 1;
	}

	if(sysctl(mib, miblen, &life, &lifelen, NULL, 0) == -1) {
		return 1;
	}
	
	printf("%d\n", life);
	
	return 0;
}
Hope it helps..
Reply With Quote
  #7   (View Single Post)  
Old 11th January 2009
BSDfan666 BSDfan666 is offline
Real Name: N/A, this is the interweb.
Banned
 
Join Date: Apr 2008
Location: Ontario, Canada
Posts: 2,223
Default

The following, from your original post.. should work.

Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysctl.h>

int
main()
{
        size_t size;
        int buf;
        size = sizeof buf;

        sysctlbyname("hw.acpi.battery.life", &buf, &size, NULL, 0);

        printf("%d\n", buf);
        return 0;
}
Take care pal.

EDIT: Fixed the above code, should work now.

Last edited by BSDfan666; 11th January 2009 at 11:11 PM.
Reply With Quote
  #8   (View Single Post)  
Old 11th January 2009
Carpetsmoker's Avatar
Carpetsmoker Carpetsmoker is offline
Real Name: Martin
Tcpdump Spy
 
Join Date: Apr 2008
Location: Netherlands
Posts: 2,243
Default

Ok, the problem with the C example was the wrong printf() statement, as anemos pointed out.

The problem with the python example was that I used the wrong type for buf, string instead of int.

For those interested, a working python example:
Code:
import ctypes

libc = ctypes.CDLL('libc.so')
size = ctypes.c_size_t()
buf = ctypes.c_int()
size.value = ctypes.sizeof(buf)
libc.sysctlbyname("hw.acpi.battery.life", ctypes.byref(buf), ctypes.byref(size), None, 0)

print buf.value
However, BSDFan666 pointed out over jabber that the apm(8) command is a more convenient and portable way of getting the same information ... Thanks!
__________________
UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things.
Reply With Quote
  #9   (View Single Post)  
Old 12th January 2009
roddierod's Avatar
roddierod roddierod is offline
Real Name: Rod Person
VPN Cryptographer
 
Join Date: Apr 2008
Location: Pittsburgh, Pa
Posts: 437
Default

Python you could have done:

Code:
import commands

def CheckBattery():
  return commands.getstatusoutput("sysctl hw.acpi.battery.life")[1].split(:)[1]
__________________
"The basic tool for the manipulation of reality is the manipulation of words. If you can control the meaning of words, you can control the people who must use the words." -Philip K. Dick
Reply With Quote
Old 12th January 2009
TerryP's Avatar
TerryP TerryP is offline
Arp Constable
 
Join Date: May 2008
Location: USofA
Posts: 1,547
Default

If you're going to play with external applications: you should use the subprocess module, not commands. I believe the getstatusoutput() function was also moved to subprocess in py26, and commands is kaput in py30; in favor of subprocess.
__________________
My Journal

Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''.
Reply With Quote
Old 13th January 2009
roddierod's Avatar
roddierod roddierod is offline
Real Name: Rod Person
VPN Cryptographer
 
Join Date: Apr 2008
Location: Pittsburgh, Pa
Posts: 437
Default

For more complex external commands I usually do, but I just thought subprocess was overkill for this.

Didn't know commands was gone in 3 thought, thanks.
__________________
"The basic tool for the manipulation of reality is the manipulation of words. If you can control the meaning of words, you can control the people who must use the words." -Philip K. Dick
Reply With Quote
Old 24th January 2009
Carpetsmoker's Avatar
Carpetsmoker Carpetsmoker is offline
Real Name: Martin
Tcpdump Spy
 
Join Date: Apr 2008
Location: Netherlands
Posts: 2,243
Default

@roddierod
That's what I did, but using ctypes would be a better since it doesn't spawn a shell.
__________________
UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 02:14 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Content copyright © 2007-2010, the authors
Daemon image copyright ©1988, Marshall Kirk McKusick