Nouvelle version de la documentation pour le demon oupsd.

/*
* Oupsd:       monitoring des lignes dcd et dsr sur port serie
*              pour simuler un onduleur et arreter une machine
*              sous linux, ayant des problemes de clavier et
*              aucune connection reseau pour se connecter.
* Usage:       oupsd /dev/ttyS0 (or any other serial device) number.
*
* Author:      R. Suinot, < rsuinux@gmx.fr >.
*
* Tres largement inspire de:
*              powerd de Miquel van Smoorenburg, < miquels@drinkel.cistron.nl >
*              en sa version 1.31, du 29-Feb-1996
*              et de:
*              setserialbits.c du Alessandro Rubini, rubini@ipvvis.unipv.it.
*
* Version:     1.0  29 Avril 2002
*
*
*  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.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Library General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
 
/* Use the new way of communicating with init. */
#define NEWINIT
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <syslog.h>
#include <string.h>
#include <ctype.h>
#include "paths.h"
#ifdef NEWINIT
#include "initreq.h"
#endif

#include <linux/kd.h>

#ifndef SIGPWR
# define SIGPWR SIGUSR1
#endif

#ifdef NEWINIT
void alrm_handler( void );

void alrm_handler()
{
}
#endif

/* Define personnel pour les signaux recus */
#define _OUPS_INIT 16390
#define _OUPS_DSR  16646
#define _OUPS_DCD  16454

/* La definition de PWRSTAT est obligatoire (definition du fichier de status nécésaire à init) */
#define PWRSTAT	"/etc/powerstatus"

#ifndef CLOCK_TICK_RATE
#define CLOCK_TICK_RATE 1193180
#endif

/* Meaningful Defaults */
#define DEFAULT_FREQ       1000
#define DEFAULT_LENGTH     50
#define DEFAULT_REPS       1
#define DEFAULT_DELAY      100	/* milliseconds */

/*
j'utilise une partie du code de beep-current (version beep-1.0.2)
pour envoyer un beep sur le buzer
*/
typedef struct
{
	int freq;			/* tone frequency (Hz)      */
	int length;			/* tone length    (ms)      */
	int reps;			/* # of repetitions         */
	int delay;			/* delay between reps  (ms) */
}
beep_parms_t;

/* ------------------------------------------------------------------------------------------------ */
/* Déclarations des fonctions */
void powerfail (int ok);
void play_beep (beep_parms_t parms);

/* ------------------------------------------------------------------------------------------------ */

/* Tell init the power has either gone or is back. */
void powerfail (ok)
int ok;
{
int fd;

	/* Creation d'un fichier d'initialisation pour init */
	unlink (PWRSTAT);
	if ((fd = open (PWRSTAT, O_CREAT | O_WRONLY, 0644)) >= 0)
	{
		if (ok == 0)
			write (fd, "FAIL\n", 5);
		else if (ok == 1)
			write (fd, "OK\n", 5);
		else
			write (fd, "LOW\n", 5);
	close (fd);
	}
	else
	{
		syslog (LOG_INFO, "Could not open or create /etc/powerfail for writing");
	}
kill(1, SIGPWR);
}

/* fonction beeper */
void play_beep (beep_parms_t parms)
{
int console_fd = -1;
int i;			/* loop counter */

	/* try to snag the console */
	if ((console_fd = open ("/dev/console", O_WRONLY)) == -1)
	{
		syslog (LOG_INFO, "Could not open /dev/console for writing");
		exit (1);
	}

	/* Beep */
	for (i = 0; i < parms.reps; i++)
	{				/* start beep */
		if (ioctl (console_fd, KIOCSOUND, CLOCK_TICK_RATE / parms.freq) < 0)
		{
			syslog (LOG_INFO, "error with ioctl.");
		}
		usleep (1000 * parms.length);	/* wait...    */
		ioctl (console_fd, KIOCSOUND, 0);	/* stop beep  */
		usleep (1000 * parms.delay);	/* wait...    */
	}				/* repeat.    */

	close (console_fd);
}



/* Main program. */
int main (int argc, char **argv)
{
char *me = argv[0];
int fd;
int flags, timeout = 2;
int oldstatus = 0;
int count = 0, etat = 0;
uint mask = ~0, outb = 0;
beep_parms_t parms = { DEFAULT_FREQ, DEFAULT_LENGTH, DEFAULT_REPS, DEFAULT_DELAY };

	if (argc != 2 || !strcmp (argv[1], "--help") || !strcmp (argv[1], "-h"))
	{
		printf (" Usage: \"%s <device> a\"\n", me);
		printf ("    <device>        is a serial device, like /dev/ttyS0 or /dev/oups\n"
			"    a number        report data every that many seconds\n\n");
		exit (1);
	}

	/* Demarrage de syslog. */
	openlog ("oupsd", LOG_CONS | LOG_PERROR | LOG_PID, LOG_DAEMON);

	/* si on ne peut pas ouvrir le periferique de sortie, on quitte */
	if ((fd = open (argv[1], O_RDWR | O_NDELAY)) < 0)
	{
		syslog (LOG_ERR, "%s: %s: %s\n", me, argv[1], sys_errlist[errno]);
		closelog ();
		exit (1);
	}

	/* on traite le second parametre passe au demarrage */
	if (isdigit (**argv))
		timeout = atoi (*argv);

	/* On passe en mode 'demon' */
	switch(fork())
	{
		case 0: /* je suis le fils */
			syslog(LOG_INFO, "Demarrage du demon oupsd: ok.");
			closelog();
			setsid();
		break;
		case -1: /* Error: passage en demon rate! */
			syslog(LOG_ERR, "can't fork.");
			closelog();
			exit(1);
		default: /* je suis le pere */
			closelog();
			exit(0);
	} 

	/* Restart syslog. */
	openlog("oupsd", LOG_CONS|LOG_PID, LOG_DAEMON);

	/* Modif perso */
	mask &= ~TIOCM_DTR;
	outb |= TIOCM_DTR;

	/* On ouvre la ligne avec les parametres de depart. Force it anyway to be sure. */
	ioctl (fd, TIOCMGET, &flags);
	flags &= mask;
	flags |= outb;
	ioctl (fd, TIOCMSET, &flags);

	/* Demande le status actuel */
	ioctl (fd, TIOCMGET, &flags);
	/* Calcul le status actuel, et le garde de coté pour les testes de differences. */
	oldstatus = flags;

	switch ( flags )
	{
		case _OUPS_INIT:
			etat++;
			syslog (LOG_INFO, "Status au demarrage: ok" );
		break;
		case _OUPS_DSR:
		case _OUPS_DCD:
			syslog (LOG_INFO, "Le peripherique n'est pas dans l'etat attendu au demarrage.");
		break;
	}

	/* a present, on scrute les lignes DSR et DCD, on n'agit que lorsqu'il y aura
	* une difference entre status et oldstatus  */
	while (1)
	{
		/* Get the status. */
		ioctl (fd, TIOCMGET, &flags);

		if (flags != oldstatus)
		{	/* changement de valeur de status */
			if (flags == _OUPS_INIT)
			{			/* le bouton est passé à l'état de départ, parce qu'on n'y était pas encore */
				if (etat == 0)
				{	/* c'est une mise à l'état de départ */
					oldstatus = flags;
					etat++;
					count = 0;
					play_beep (parms);
					syslog (LOG_INFO, "Remise à zéro du bouton.");
				}
			}
			else
			{	/* on est passé soit à _OUPS_DCD soit à _OUPS_DSR */
				play_beep (parms);
				parms.reps++;
				if (flags == _OUPS_DSR)
				{		/* demande d'arret de la machine */
					syslog (LOG_INFO, "modification sur DSR (%i) ", count);
				}
				else if (flags == _OUPS_DCD)
				{		/* demande d'arret du serveur X */
					syslog (LOG_INFO, "modification sur DCD (%i) ", count);
				}

				if (count++ > 2)
				{	/* Si cela fait 3 fois que le status est changé, alors ce n'est pas une erreur,
					 * on envoi un mesage a init en fonction du message */
					parms.freq += 5000;
					parms.reps += 2;
					play_beep (parms);
					if (flags == _OUPS_DSR)
					{		/* demande d'arret de la machine */
						syslog (LOG_INFO, "Signal envoyé vers le processus init: ARRET SYSTEME ");
						powerfail (2);
					}
					else if (flags == _OUPS_DCD)
					{	/* demande d'arret du serveur X */
						syslog (LOG_INFO, "Signal envoyé vers le processus init: ARRET PARTIEL ");
						powerfail (0);
					}
					oldstatus = flags;	/* on change la valeur de oldstatus, et on simule un demarrage avec le  */
					etat--;				/* bouton mal positionne */
					count = 0;
					parms.reps = 1;
					parms.freq = DEFAULT_FREQ;
				}
			}
		}
		else if (flags == _OUPS_INIT)
		{	/* on essai d'annuler le changement demandé */
			if (count != 0)
			{	/* on s'est trompe, apparemment? donc on demande la restauration du processus init */
				syslog (LOG_INFO, "Annulation de la demande d'arret du systeme.");
				oldstatus = flags;
				count = 0;
				parms.reps = 1;
				parms.freq = 3000;
				play_beep (parms);
				parms.freq = DEFAULT_FREQ;
			}
		}
		sleep (timeout);
	}
	return (0);
}

Ce site est continuellement en chantier, surtout la partie 'Journal de bord' (cf 'Documentations').
Cependant, vous pouvez quand même me contacter et me donner vos avis/idées/corrections à rsuinux <at> gmx.fr

Mise en place du site:   11 Juillet 2001     Dernière mise à jour: 11/05/04

Vous êtes     à être passé me voir!

Valid HTML 4.01! Valid CSS!