my blog

Informatique

Entries feed

Wednesday 18 August 2004

Présentation LaTeX

Tout le monde connait les présentations PowerPoint. Maintenant, les gens commencent à utiliser OpenOffice.org, et quelques anciens du monde Un*x utilisent MagicPoint. Mais voilà, quand on n'est pas sous Windows (pas de PowerPoint), et que les deux autres logiciels ne conviennent pas pour diverses raisons, il faut utiliser autre chose.

LaTeX peut nous sauver, pense-t-on. Et c'est vrai. Mais ce n'est pas facile, car il faut installer quelques paquets LaTeX. On a vu des gens utiliser une classe foils, donc on cherche parmi les paquets de sa distribution celui qu'il faut. On trouve (après un bout de temps) qu'il s'agit du paquet LaTeX foiltex. Pas de chance : sur Fedora, il n'y a pas de RPM, car ce n'est pas libre et en fait, c'est pareil pour Debian. On rechigne, mais on l'installe quand même à la main.

On est content, et puis on voit un exemple qui utilise certains paquets LaTeX pause.sty, background.sty, pp4slide.sty. En fait, il s'agit de paquets LaTeX pour avoir de biens beaux PDF. En cherchant un peu, on découvre que ceux-ci sont téléchargeables à partir de la page de PPower4. Et toujours pas de paquet pour ma distribution. Snifff...

J'aurai donc une belle présentation, mais il aura fallu installer des choses à la main. Suis-je le seul à penser que ce n'est pas normal ?

Friday 6 August 2004

g_log et threads

J'ai fait, par hasard, une petite découverte. GLib possède une fonctionnalité intéressante permettant de logger des messages. C'est très pratique et je vous encourage vivement à l'utiliser. Je l'utilisais dans un programme assez conséquent (en taille) et cela fonctionnait très bien, et puis tout d'un coup, j'ai commencé à avoir des bugs. Sans raison apparente. Il y avait juste un petit message qui ressemble à ceci :

(process:608): MyLogDomain-LOG-0x100 (recursed): one log message of my program

aborting...

Et là, ce fut le début de la panique, qui a duré quelques heures. Après avoir regardé le code de la GLib, puis après avoir cherché sur Internet, j'ai commencé à saisir le problème. La solution est ici. Et oui, j'utilise des threads. Mais on ne m'a jamais prévenu qu'il fallait faire quelque chose de spécial...

Donc voici un petit programme pour constater ce qui se passe :

/* Compile like this to see the crash:
      gcc -o testlog -pthread `pkg-config --cflags --libs glib-2.0 gthread-2.0` testlog.c
  or like this to make it work:
      gcc -o testlog -DUSE_GTHREAD -pthread `pkg-config --cflags --libs glib-2.0 gthread-2.0` testlog.c
 */
#include <glib.h>
#include <pthread.h>

#define MY_LOG_DOMAIN "MyLog"
#define MAX_COUNT 1000

static void
log_handler (const gchar    *log_domain,
	     GLogLevelFlags  log_level,
	     const gchar    *message,
             gpointer        user_data)
{
	g_print (message);
}

static void *
count_thread (void *arg)
{
	int max_count = GPOINTER_TO_INT (arg);
	int i;
	int pid = getpid ();

	for (i = 0; i < max_count; i++) {
		g_log (MY_LOG_DOMAIN, 1 << G_LOG_LEVEL_USER_SHIFT,
		       "other thread (%d) - count %d\n", pid, i);
	}

	pthread_exit (NULL);
}

static void *
count (int max_count)
{
	int i;
	int pid = getpid ();

	for (i = 0; i < max_count; i++) {
		g_log (MY_LOG_DOMAIN, 1 << G_LOG_LEVEL_USER_SHIFT,
		       "main thread (%d) - count %d\n", pid, i);
	}
}

int main
(int argc, char **argv)
{
	pthread_t thread;
	guint handler_id;

#ifdef USE_GTHREAD
	g_thread_init (NULL);
#endif

	handler_id = g_log_set_handler (MY_LOG_DOMAIN, ~0, log_handler, NULL);
	if (handler_id == 0)
		return 1;

	if (pthread_create (&thread, NULL, &count_thread,
			    GINT_TO_POINTER (MAX_COUNT)) != 0) {
		g_log_remove_handler (MY_LOG_DOMAIN, handler_id);
		perror ("pthread_create");
		return 1;
	}

	count (MAX_COUNT);

	pthread_join (thread, NULL);

	g_log_remove_handler (MY_LOG_DOMAIN, handler_id);

	return 0;
}

Du coup, j'ai ouvert un petit bug.

Friday 30 July 2004

LaTeX, A4 et letter (suite)

Je préfère écrire la réponse ici, et pas en commentaire à la précédente entrée.

Après avoir un petit peu plus cherché (c'est facile, quand on connait plus précisément le problème), il apparait que je ne suis pas le seul à avoir ce problème. Et il existe visiblement une solution un peu plus simple que celle que j'ai indiquée précédemment. Il suffit d'ajouter au début du fichier .tex :

\pdfpagewidth=8.5 true in
\pdfpageheight=11 true in

Ce qui est dommage, c'est que les développeurs n'ont pas l'air de saisir qu'une option de ligne de commande serait utile pour cela... (mais il est vrai que beaucoup d'autres options méritent aussi d'être en ligne de commande).

LaTeX, A4 et letter

La différence, c'est bien. Mais bon, c'est aussi assez embêtant de temps en temps. Prenez par exemple le papier. Il a une taille standard : le A4. Cela doit être standard partout dans le monde. Sauf aux Etats-Unis (et certainement dans quelques autres pays aussi, mais chut...) : là-bas, la taille standard est letter. Pas bien grave, me direz-vous. Et bien si. Quand on doit envoyer un article à des américains, ils le veulent au format letter. Pas de problème. Sauf quand on utilise LaTeX.

En effet, LaTeX, lorsqu'il est installé chez des pauvres européens, est configuré pour générer du A4. Et il n'est pas possible de lui faire générer facilement un autre format. C'est une horreur, particulièrement quand on utilise pdflatex (et qu'on n'a pas le choix car on a des images au format PDF). Il faut trouver les bons fichiers de configuration et les éditer. Voici donc ce qu'il faut faire.

Pour corriger dvips, il faut éditer /usr/share/texmf/dvips/config/config.ps et changer les lignes :

@ A4size 210mm 297mm
@+ %%PaperSize: A4

en les commentant avec % :

% @ A4size 210mm 297mm
% @+ %%PaperSize: A4

Je ne suis pas du tout sûr que ce soit une solution propre... On peut modifier le comportement de dvips sans modifier la configuration par défaut en utilisant l'option -t letter dans la ligne de commande.

Pour corriger pdflatex (ce qui m'intéressait vraiment), il faut éditer /usr/share/texmf/pdftex/config/pdftex.cfg et changer les lignes :

page_width 210 true mm
page_height 297 true mm

en ceci :

page_width 8.5 true in
page_height 11 true in

Et là, il n'y a pas d'option de ligne de commande pour modifier le comportement par défaut. Donc, à moins que quelqu'un ne prenne le temps d'écrire un patch ou de reporter le problème au bon endroit, c'est la seule solution à mon problème (du moins, seule solution que je connais).

Source de la solution : cette entrée dans le journal de David Mellis.

gethostname et FQDN

Plusieurs programmes ont besoin d'avoir le FQDN de l'hôte sur lequel ils tournent, notamment lorsqu'ils communiquent avec des programmes ou des personnes utilisant une autre machine. Le réflexe naturel est d'utiliser gethostname. Seulement voilà : gethostname peut parfois retourner le nom de l'hôte, sans le domaine. Ainsi, il est possible que gethostname renvoie 3rivieres alors que je souhaite obtenir 3rivieres.vuntz.net. Et le problème est qu'il n'y a pas de recette miracle pour obtenir directement 3rivieres.vuntz.net. Il faut mettre les mains dans le cambouis. Voici un petit exemple de code qui montre comment faire.

#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif

static void is_fqdn (char *display, char *name)
{
	if (strchr (name, '.') != NULL) {
		if (strncasecmp (name, "localhost", 9) == 0) {
			printf ("%s is a FQDN, but it's localhost: "
				"%s\n", display, name);
		} else {
			printf ("%s is a FQDN: %s\n", display, name);
		}
	} else {
		printf ("%s isn't a FQDN: %s\n", display, name);
	}
}

int main (int argc, char **argv)
{
	char             hostname[HOST_NAME_MAX];
	struct hostent  *he;
	char           **alias;
	char             buffer[64];

	if (gethostname (hostname, HOST_NAME_MAX)) {
		perror("gethostname");
		return 1;
	}

	/* man gethostname(2): we don't know if hostname is NUL-terminated */
	hostname[HOST_NAME_MAX - 1] = '\0';

	is_fqdn ("gethostname return value", hostname);

	he = gethostbyname (hostname);
	if (he == NULL) {
		herror ("gethostbyname");
		return 1;
	}

	is_fqdn ("The name returned by gethostbyname", he->h_name);

	alias = he->h_aliases;
	while (alias && *alias) {
		snprintf (buffer, 64, "Alias %d returned by gethostbyname",
			  alias + 1 - he->h_aliases);
		is_fqdn (buffer, *alias);
		alias++;
	}

	return 0;
}

Allez, maintenant, j'envoie un petit patch aux auteurs de libspf2 pour pouvoir fermer mon bug.

- page 10 of 16 -

by Vincent