jun
06
2010

idéia inspiradas por applescript, kde e d-bus

Tudo começou numa tentativa que fiz para automatizar uma tarefa - reiniciar o AirPort no MacOSX - em 10 minutos no Google consegui as informações necessárias para fazer um script na linguagem AppleScript. Isso me fez pensar em algumas coisas sobre a interatividade que obtemos nos ambientes atuais e as possibilidades nos ambientes livres.

Veja um exemplo feito no AppleScript simples para mostrar a janela com as preferências de rede (System Preferences -> Network).

Nota: (1) se o você for testar e seu sistema estiver em Português, lembre-se de traduzir os nomes entre aspas.  (2) Para rodar os scripts é preciso marcar a opção Enable access for assistive Devices em System Preferences -> Universal Access
tell application "System Preferences"
	activate
	set current pane to pane "com.apple.preference.network"
end tell

Para desligar/ligar o AirPort:

tell application "System Events"
	tell process "System Preferences"
		tell window "Network"
			tell group 1
				if (exists button "Turn Airport Off") then
					click button "Turn AirPort Off"
					delay 3
				end if
				if (exists button "Turn Airport On") then
					click button "Turn AirPort On"
				end if
			end tell
		end tell
	end tell
end tell

Veja que é uma tradução em palavras (praticamente verbos no imperativo) do que seria o processo feito no modo gráfico. Se você programa em Python, existe um comparativo.

Ambientes livres

E é justamente com Python que vejo uma alternativa interessante para controlar as aplicações como o System Settings. Talvez o jeito mais fácil de fazer isso seria através de uma comunicação IPC como o D-BUS . Inclusive o system settings é exportado em org.kde.systemsettings.

$ qdbus org.kde.systemsettings

Resumindo, o acesso pode não ser tão fácil quanto no AppleScript mas o “meio” já existe em ambiente gráficos tal como KDE e  GNOME. O Python lida muito bem com este tipo de comunicação e é uma saída para quem está procurando um jeito para controlar seu ambiente de forma automatizada.

Futuro

Na minha opinião há uma deficiência para (A) pessoas leigas, se quiserem, controlar seus aplicativos de forma automatizada e (B) melhorar as formas de usabilidade nas interfaces existentes.

Fico imaginando se não seria interessante um investimento (e pesquisa) para criar linguagens de programação que herdem construções da “fala” para acessar aplicativos, para no futuro utilizar da “voz” humana para controlar o computador.

O software livre é um terreno vasto para esse tipo de experiência. Cito algumas tecnologias que tornaria isso possível:

  • D-bus para comunicação entre os aplicativos
  • Python como linguagem de programação para construir as “amarras”
  • NTLK (Natural Language Toolkit) para processar a linguagem

Se você trabalhar com algum tipo de pesquisa na área ou tem experiência, por favor, deixe um comentário.

Bom começo de semana a todos.

mai
31
2010

Básico de passagem de parâmetros em C++

para não acontecer certos erros que vi por aí…

Em C++ há três maneiras de passar um parâmetro para uma função, as tradicionais herdadas da linguagem C: valor e ponteiro; além da novidade: a passagem por referência. Para ilustrar veja o seguinte exemplo, passar uma estrutura de dados “grande” (neste caso aproximadamente 10 kilobytes) para uma função:

#include<iostream>
#include <string.h>

using namespace std;

struct Big {
char text[10000];
int id;
};

void f1( Big v ) {
cout << v.text << endl;
cout << “Ox” << hex << v.id << endl;
}

void f2( const Big *v ) {
cout << v->text << endl;
cout << “Ox” << hex << v->id << endl;
}

void f3( const Big &v ) {
cout << v.text << endl;
cout << “Ox” << hex << v.id << endl;
}

int main(int /*argc*/, char * /*argv*/[]) {

Big *b0 = new Big;
Big b1;
Big &b2 = b1;

strcpy(b0->text,“asdfg asdfg asdf asdf asdf asdf”);
strcpy(b1.text,“azsxd azsxd azsxd azsxd azsxd azsxd”);

b0->id = 0xbc;
b1.id = 0xde;

f2( b0 ); /* pointer */
f1( b1 ); /* value */
f3( b2 ); /* reference */
}


Veja o código assembly gerado pelo compilador (g++) para cada um dos três casos:

1) Ponteiro

mov    -0xc(%ebp),%eax
mov    %eax,(%esp)
call   0x8048885

2) Valor

movl   $0x0,-0x2728(%ebp)
lea    -0x2720(%ebp),%eax
mov    %eax,-0x272c(%ebp)
jmp    0x8048a36
mov    -0x272c(%ebp),%ecx
mov    -0x2728(%ebp),%edx
movzbl (%ecx,%edx,1),%eax
mov    -0x2728(%ebp),%edx
mov    %al,(%esp,%edx,1)
addl   $0x1,-0x2728(%ebp)
cmpl   $0x2714,-0x2728(%ebp)
jb     0x8048a16
call   0x80488fe

3) Referência

mov    -0x8(%ebp),%eax
mov    %eax,(%esp)
call   0x804880c

Talvez seja importante:

  • Se você prefere a sintaxe da intel? Mude no GDB: set disassembly-flavor intel
  • Não precisa ser muito esperto para ver que a passagem por valor é a pior de todas, veja quanto código assembly foi gerado [#fail]
  • A passagem por referência é inclusive mais eficiente pois aloca no %ebp (base pointer) [8 bytes ao invés de 12 bytes do ponteiro].
  • A passagem por referência provê a eficiência da passagem por ponteiros com a clareza da passagem por valor.
mai
10
2010

td

Estou utilizando o Vim et all, para escrever o texto do meu trabalho de conclusão de curso (conhecido também como trabalho de diploma, td), são basicamente as ferramentas:

  1. vim – editor
  2. aspell – correção ortográfica
  3. bibtex – referencias textuais
  4. latex – processador de texto
  5. abntex – padrão do documento

A norma (!) diz que as palavras estrangeiras devem ser escritas em itálico. Como é um texto técnico, há o uso frequente de palavras in english e o risco de deixar uma para trás é grande. Como a motivação para não escrever é maior, dispersei e acabei fazendo um programa que a partir de uma entrada (CSV) varre o texto e insere o itálico quando for necessário. O protótipo até agora esta assim:

O código ainda não está limpo para torná-lo acessível num repositório on-line. Além disso, acho que há outras maneiras mais eficazes: sed, python, etc. Como não sei quando vou ter tempo para torná-lo útil de verdade, vou colar aqui as duas partes do código que achei interessante.

A alteração no texto é simples: primeiro varremos o texto procurando pelo termo (*palavra é um iteraror da QStringList) e associamos um índice para cada ocorrência (indexOf) adicionando em uma lista (pos é um QList<int>). Antes de fazermos a troca (replace) comparamos com outra lista (blacklist) se essa inserção já não está dentro de um \textit. Se isso não acontecer, pode existir casos do tipo: \textit{\textit{itálico}}.

while ((i=s.indexOf(*palavra,i+1)) != -1)
	pos << i;

for (index=0, offset=0; index < pos.length() ; index++)
	if (blacklist.contains(pos.at(index)) == false) {
		str = "\\textit{" + *palavra + "}";
		s.replace(pos.at(index)+offset,(*palavra).length(),str);
		offset += 9;
	}

A construção da blacklist pode também ser aproveitada para evitar outros contextos, como notas de rodapé. Apenas trocar o \\textit pelo \\footnote.

while ((a=s.indexOf("\\textit{",b+1)) != -1) {
	b = s.indexOf("}",a);
	if ((c=s.indexOf(*palavra,a)) < b)
		blacklist << s.indexOf(*palavra,a);
}

Conclusão: esse post nem era para existir, mas quem sabe eu não invento algum programa que escreva o texto sozinho :P

Até mais!

abr
29
2010

latex + abntex

Estou fazendo uma série de experimentos com um conceito novo para apresentações, já refiz uma palestra apresentada no Calourada Livre e agora um teste em forma de tutorial. Penso que boa parte do sucesso deste tipo de abordagem é a busca contemporânea por informação rápida. Note, tudo que fiz está disponível na documentação. Entretanto, a estética como é apresentado facilita a compreensão. Esta apresentação mostra uma maneira independente de instalar o pacote abntex utilizado para contruir documentos em conformidade com o padrão definido pela ABNT.

http://prezi.com/aum-fzbgnkyl/latex-abntex/

abr
26
2010

kthreads (1)

Creating a thread at kernel-space

Now that I know that somebody at Academia reads my posts :-) I’ll put code with a _little_ documentation information together. Today we will do a quick review about kernel threads or to be more precisely, a way to perform some operations in the background. Kernel threads are standard process that:

  1. Exist solely in kernel-space.
  2. Don’t have an address space.
  3. Don’t context switch to user-space.
  4. Are schedulable and preemptable as normal process.

And let’s see an example:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/delay.h>

static int thread3(void *unused) {

	int count3 = 0;
	while (count3 < 1000) {
		msleep(100);
		printk("Thread 3: %d\n", count3++);
	}
	return 0;
} 

static int thread2(void *unused) {

	int count2 = 0;
	while (count2 < 1000) {
		msleep(10);
		printk("Thread 2: %d\n", count2++);
	}
	return 0;
}

static int __init threads_init(void)
{
	int count1;
	int ret1, ret2;

	count1 = 0;
	ret1 = kernel_thread(thread2, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD );
	ret2 = kernel_thread(thread3, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD );

	printk("-- kernel thread: module init\n");
	printk("-- kernel thread: spawning thread 1 ret=%d\n", ret1);
	printk("-- kernel thread: spawning thread 2 ret=%d\n", ret2);	

	/*
	   Don't use "long" loops on init().
	   If you uncomment the snippet below the insmod will lock until while finishes
	*/ 

	/*
	while (count1 < 1000) {
		msleep(10);
		printk("Thread 1: %d\n", count1++);
     	}
	*/

    return 0;
}

static void __exit threads_exit(void)
{
    printk("-- kernel thread: module removed\n");
}

module_init(threads_init);
module_exit(threads_exit);

MODULE_AUTHOR("Tiago Maluta <maluta@unifei.edu.br");
MODULE_DESCRIPTION("kthreads examples");
MODULE_LICENSE("GPL");

Things from code that are found in docs…

  • CLONE_FS means that parent and child share filesystem information.
  • CLONE_FILES means that parent and child open files.
  • CLONE_SIGHAND means that parent and child share signal handlers.

I use arbitrarily msleep() just to allow user “see” what is happening when dumping kernel ring buffer.

abr
21
2010

latex + bibtex

Tá tudo certo e nada funciona?

Supondo que você tenha dois arquivos.

  1. artigo.tex
  2. biblio.bbl

E está tendo erros quando tenta fazer uma citação (\cite{Autor}), tipo:

  • LaTeX Warning: There were undefined references.
  • LaTeX Warning: Citation `XXXX’ on page n undefined on input line N.

Isso acontece pois alguns arquivos precisam ser gerados (basicamente o aux, bbl e blg) e há uma dependência circular. A solução é simples:

pdflatex artigo.tex
bibtex all
pdflatex artigo.tex
pdflatex artigo.tex
abr
21
2010

Adding procfs and sysfs interface in your lkml

Hi. This post will show how to add two important things about device model in your linux kernel module (lkml). Sysfs is the user-space manifestation of the kernel’s structured device model. It’s similar to procfs in that both are in-memory filesystem containing information about kernel data structures. Basically:

  • procfs is a generic window into kernel internals
  • sysfs is specific to device model

Information such as process descriptors and sysctls parameters belong to procfs and not sysfs. Note that: Sysfs is not a replacement for procfs.

Lets create two useless (in a practical way) that presents the “idea” behind these constructions.

1. Procfs

The snippet  below creates a /proc/coding allowing read or write some content.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

/* for proc_dir_entry and create_proc_entry */
#include <linux/proc_fs.h>

/* For sprintf and snprintf */
#include <linux/string.h>

/* For copy_from_user */
#include <linux/uaccess.h>

static char internal_buffer[256];

int buf_read(char *buf, char **start, off_t offset, int count, int *eof, void *data)
{
	int len;
	len = snprintf(buf, count, "%s", internal_buffer);
	return len;
}

static int buf_write(struct file *file, const char *buf, unsigned long count, void *data)
{
	if(count > 255) /* to avoid overflowwwwwwwwww */
		count = 255;

	/* Copies data from user space to kernel space */
	copy_from_user(internal_buf, buf, count);

	/* inserting NULL to end the string */
	internal_buf[count] = '\0';
	return count;
}

int __init proc_init(void) {
	/* Simple */
	struct proc_dir_entry *de = create_proc_entry("coding", 0667, 0);

	/* Set pointers to our functions */
	de->read_proc = buf_read; /* reading */
	de->write_proc = buf_write; /* writing */ 

	/* We initialize our internal_buffer with some text. */
	sprintf(internal_buffer, "www.coding.com.br");
	return 0 ;
}

void __exit proc_cleanup(void) {

	/* We delete our entry */
	remove_proc_entry("coding", NULL);

}

module_init(proc_init);
module_exit(proc_cleanup);

MODULE_LICENSE("GPL");

2. Sysfs

This example only creates a /sys/class/<module-name> directory with nothing inside. This may not be clear now but remember when I show – in the next posts – some practical use with device node (/dev).

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

/* for sysfs class creation */
#include <linux/platform_device.h>

static struct class *sysfs_class;

int __init sysfs_init(void) {

	sysfs_class = class_create(THIS_MODULE, "sysfs" );
	return 0 ;
}

void __exit sysfs_cleanup(void) {

	/* We delete our entry */
	class_destroy(sysfs_class);
}

module_init(sysfs_init);
module_exit(sysfs_cleanup);

MODULE_LICENSE("GPL");
abr
20
2010

Notify chain: example 1

This is a basic skeleton of a Linux kernel module about notify chain that I’ll put as examples on my final course paper. When user presses a key, kernel “reads” it and then, using notify chain informs all subsystems which want to be informed about pressed key.

/* keyboard-dump.c
 *
 * This is a "notify chain" example that dumps keyboard on kernel message
 *
 *	(C) Copyright 2010, Tiago Maluta
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/notifier.h>
#include <linux/module.h>
#include <linux/keyboard.h>

static int debug = 1;

#define dbg(fmt, arg...)						\
	do {								\
		if (debug)						\
			printk (KERN_DEBUG "%s: %s: " fmt "\n",		\
				"test" , __FUNCTION__ , ## arg);	\
	} while (0)

int keyboard_event_handler(struct notifier_block *self,
                         unsigned long val,
			 void *data) 

{

	struct keyboard_notifier_param *param = data; 

	unsigned int value = param->value;

	if ((!param->down) && (value > 0xf000))
		printk("%c", KVAL(param->value));

	return NOTIFY_DONE ;
}

static struct notifier_block keyboard_notifier = {

	.notifier_call = keyboard_event_handler,
};

static int __init keyboard_init(void) 

{

	register_keyboard_notifier(&keyboard_notifier);

	dbg();

	return 0;
}

static void __exit keyboard_exit(void)

{
	unregister_keyboard_notifier(&keyboard_notifier);
	dbg();
}

module_init(keyboard_init);
module_exit(keyboard_exit);

MODULE_LICENSE("GPL");
<body bgcolor="#ffffff" text="#000000">
<pre>
<font color="#444444">/* keyboard-dump.c
 *
 * This is a &quot;notify chain&quot; example that dumps keyboard on kernel message
 *
 *	(C) Copyright 2010, Tiago Maluta
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */</font>

<font color="#0000ff"><strong>#include <font color="#008000">&lt;linux/notifier.h&gt;</font></strong></font>
<font color="#0000ff"><strong>#include <font color="#008000">&lt;linux/module.h&gt;</font></strong></font>
<font color="#0000ff"><strong>#include <font color="#008000">&lt;linux/keyboard.h&gt;</font></strong></font>

<strong>static</strong> <strong>int</strong> <font color="#2040a0">debug</font> <font color="#4444ff">=</font> <font color="#ff0000">1</font><font color="#4444ff">;</font>
<font color="#0000ff"><strong>#define dbg(fmt, arg...)						\</strong></font>
	<strong>do</strong> <font color="#4444ff"><strong>{</strong></font>								\
		<strong>if</strong> <font color="#4444ff">(</font><font color="#2040a0">debug</font><font color="#4444ff">)</font>						\
			<font color="#2040a0">printk</font> <font color="#4444ff">(</font><font color="#2040a0">KERN_DEBUG</font> <font color="#008000">&quot;%s: %s: &quot;</font> <font color="#2040a0">fmt</font> <font color="#008000">&quot;<font color="#77dd77">\n</font>&quot;</font>,		\
				<font color="#008000">&quot;test&quot;</font> , <font color="#2040a0">__FUNCTION__</font> , ## <font color="#2040a0">arg</font><font color="#4444ff">)</font><font color="#4444ff">;</font>	\
	<font color="#4444ff"><strong>}</strong></font> <strong>while</strong> <font color="#4444ff">(</font><font color="#ff0000">0</font><font color="#4444ff">)</font>
<strong>int</strong> <font color="#2040a0">keyboard_event_handler</font><font color="#4444ff">(</font><strong>struct</strong> <font color="#2040a0">notifier_block</font> <font color="#4444ff">*</font><font color="#2040a0">self</font>,
                         <strong>unsigned</strong> <strong>long</strong> <font color="#2040a0">val</font>,
			 <strong>void</strong> <font color="#4444ff">*</font><font color="#2040a0">data</font><font color="#4444ff">)</font>
<font color="#4444ff"><strong>{</strong></font>

	<strong>struct</strong> <font color="#2040a0">keyboard_notifier_param</font> <font color="#4444ff">*</font><font color="#2040a0">param</font> <font color="#4444ff">=</font> <font color="#2040a0">data</font><font color="#4444ff">;</font> 

	<strong>unsigned</strong> <strong>int</strong> <font color="#2040a0">value</font> <font color="#4444ff">=</font> <font color="#2040a0">param</font><font color="#4444ff">-</font><font color="#4444ff">&gt;</font><font color="#2040a0">value</font><font color="#4444ff">;</font>
	<strong>if</strong> <font color="#4444ff">(</font><font color="#4444ff">(</font><font color="#4444ff">!</font><font color="#2040a0">param</font><font color="#4444ff">-</font><font color="#4444ff">&gt;</font><font color="#2040a0">down</font><font color="#4444ff">)</font> <font color="#4444ff">&amp;</font><font color="#4444ff">&amp;</font> <font color="#4444ff">(</font><font color="#2040a0">value</font> <font color="#4444ff">&gt;</font> <font color="#ff0000">0xf000</font><font color="#4444ff">)</font><font color="#4444ff">)</font>
		<font color="#2040a0">printk</font><font color="#4444ff">(</font><font color="#008000">&quot;%c&quot;</font>, <font color="#2040a0">KVAL</font><font color="#4444ff">(</font><font color="#2040a0">param</font><font color="#4444ff">-</font><font color="#4444ff">&gt;</font><font color="#2040a0">value</font><font color="#4444ff">)</font><font color="#4444ff">)</font><font color="#4444ff">;</font>
	<strong>return</strong> <font color="#2040a0">NOTIFY_DONE</font> <font color="#4444ff">;</font>
<font color="#4444ff"><strong>}</strong></font>

<strong>static</strong> <strong>struct</strong> <font color="#2040a0">notifier_block</font> <font color="#2040a0">keyboard_notifier</font> <font color="#4444ff">=</font> <font color="#4444ff"><strong>{</strong></font>
	.<font color="#2040a0">notifier_call</font> <font color="#4444ff">=</font> <font color="#2040a0">keyboard_event_handler</font>,
<font color="#4444ff"><strong>}</strong></font><font color="#4444ff">;</font>

<strong>static</strong> <strong>int</strong> <font color="#2040a0">__init</font> <font color="#2040a0">keyboard_init</font><font color="#4444ff">(</font><strong>void</strong><font color="#4444ff">)</font>
<font color="#4444ff"><strong>{</strong></font>

	<font color="#2040a0">register_keyboard_notifier</font><font color="#4444ff">(</font><font color="#4444ff">&amp;</font><font color="#2040a0">keyboard_notifier</font><font color="#4444ff">)</font><font color="#4444ff">;</font>
	<font color="#2040a0">dbg</font><font color="#4444ff">(</font><font color="#4444ff">)</font><font color="#4444ff">;</font>
	<strong>return</strong> <font color="#ff0000">0</font><font color="#4444ff">;</font>
<font color="#4444ff"><strong>}</strong></font>
<strong>static</strong> <strong>void</strong> <font color="#2040a0">__exit</font> <font color="#2040a0">keyboard_exit</font><font color="#4444ff">(</font><strong>void</strong><font color="#4444ff">)</font>
<font color="#4444ff"><strong>{</strong></font>
	<font color="#2040a0">unregister_keyboard_notifier</font><font color="#4444ff">(</font><font color="#4444ff">&amp;</font><font color="#2040a0">keyboard_notifier</font><font color="#4444ff">)</font><font color="#4444ff">;</font>
	<font color="#2040a0">dbg</font><font color="#4444ff">(</font><font color="#4444ff">)</font><font color="#4444ff">;</font>
<font color="#4444ff"><strong>}</strong></font>
<font color="#2040a0">module_init</font><font color="#4444ff">(</font><font color="#2040a0">keyboard_init</font><font color="#4444ff">)</font><font color="#4444ff">;</font>
<font color="#2040a0">module_exit</font><font color="#4444ff">(</font><font color="#2040a0">keyboard_exit</font><font color="#4444ff">)</font><font color="#4444ff">;</font>

<font color="#2040a0">MODULE_LICENSE</font><font color="#4444ff">(</font><font color="#008000">&quot;GPL&quot;</font><font color="#4444ff">)</font><font color="#4444ff">;</font>
</pre>

The output will be visible (i.e: dmesg) on kernel ring buffer.

If you like try don’t cut&paste the code above but use I gist repository here.