TOP
Section : CONFIG.C
/* $Id: config.c,v 1.7 2001/09/24 00:59:02 wyy Exp $ */
/*
* config.c
*
* Remote Sensory Control and Data Acquisition Daemon
*
* William Emmanuel S. YU
* Ateneo de Manila University, Philippines
*
* See README for more information.
*/
#include "scadad.h"
/**
* scada_generic_config () - reading configuration generic settings
**/
int scada_generic_config (const char *configfile)
{
FILE *confd;
char buf[BUFSIZE];
char sendpath[MAXLINE];
char number[MAXLINE];
int semid;
struct scadadstruct *scadad;
char *temp;
/* open config file */
if ((confd = fopen(configfile, "r")) == NULL) {
printf ("SCADA error: could not open config filename: %s\n", configfile);
return -1;
}
/* read data from config file */
while (fgets (buf, BUFSIZE, confd) != NULL) {
/* grab module directory line first */
if ( strncmp (buf, "smssendpath", 11) == 0) {
sscanf (buf, "smssendpath %s", sendpath);
if (( temp = (char*) malloc (strlen (sendpath) + 1) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
exithandl (1);
}
strcpy (temp, sendpath);
/* set the controlpid member of the control structure */
semid = sem_open (SEMKEY);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->sms.sendpath = temp;
scadad->sms.status = SERVICE_ON;
sem_signal (semid);
}
/* grab module directory line first */
if ( strncmp (buf, "smsnumber", 9) == 0) {
sscanf (buf, "smsnumber %s", number);
if (( temp = (char*) malloc (strlen (number) + 1) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
exithandl (1);
}
strcpy (temp, number);
/* set the controlpid member of the control structure */
semid = sem_open (SEMKEY);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->sms.number = temp;
scadad->sms.status = SERVICE_ON;
sem_signal (semid);
}
}
fclose (confd);
return 0;
} /* scada_generic_config */
/**
*
* scada_module_config () - read config file settings. the mood configuration
* settings are stored in a linked list and the pointer to the head
* is returned.
*
*/
struct modulelist *scada_module_config (const char *configfile)
{
FILE *confd;
char buf[BUFSIZE];
struct modulelist *head;
struct modulelist *curr;
struct modulelist *tempstruct;
char *temp;
char *temp2;
char name[BUFSIZE];
char path[BUFSIZE];
char fullpath[BUFSIZE];
head = curr = tempstruct = NULL;
/* open config file */
if ((confd = fopen(configfile, "r")) == NULL) {
printf ("SCADA error: could not open config filename: %s\n", configfile);
return NULL;
}
/* read data from config file */
while (fgets (buf, BUFSIZE, confd) != NULL) {
/* grab module directory line first */
if ( strncmp (buf, "modpath", 7) == 0) {
sscanf (buf, "modpath %s", fullpath);
}
/* module settings */
if ( strncmp (buf, "module", 6) == 0) {
sscanf (buf, "module %s %s", name, path);
if (( temp = (char *) malloc (strlen (name) + 1) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
}
strcpy (temp, name);
if (( temp2 = (char *) malloc (strlen (path) + strlen (fullpath) + 2) )
== NULL) {
printf ("SCADA error: memory allocation error\n");
}
strcpy (temp2, fullpath);
strcat (temp2, "/");
strcat (temp2, path);
if (( tempstruct = (struct modulelist *) malloc (
sizeof (struct modulelist)) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
exithandl (1);
}
tempstruct->name = temp;
tempstruct->path = temp2;
if ( head == NULL ) {
head = tempstruct;
curr = tempstruct;
tempstruct->next = NULL;
} else {
curr->next = tempstruct;
tempstruct->next = NULL;
curr = tempstruct;
}
}
}
fclose (confd);
return head;
} /* scada_module_config */
/**
*
* scada_mood_config() - read config file settings. the mood configuration
* settings are stored in a linked list and the pointer to the head
* is returned.
*
*/
struct moodstruct *scada_mood_config (const char *configfile)
{
FILE *confd;
char buf[BUFSIZE];
struct moodstruct *head;
struct moodstruct *curr;
struct moodstruct *tempstruct;
char *temp;
char moodname[BUFSIZE];
int moodnum, lightlvl, templvl, playlist;
head = curr = tempstruct = NULL;
/* open config file */
if ((confd = fopen(configfile, "r")) == NULL) {
printf ("SCADA error: could not open config filename: %s\n", configfile);
return NULL;
}
/* read data from config file */
while (fgets (buf, BUFSIZE, confd) != NULL) {
/* mood settings */
if ( strncmp (buf, "mood", 4) == 0) {
sscanf (buf, "mood %s %d %d %d %d", moodname,
&moodnum, &lightlvl, &templvl, &playlist);
if (( temp = (char *) malloc (strlen (moodname) + 1) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
}
strcpy (temp, moodname);
if (( tempstruct = (struct moodstruct *) malloc (
sizeof (struct moodstruct)) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
exithandl (1);
}
tempstruct->moodname = temp;
tempstruct->moodnum = moodnum;
tempstruct->lightlvl = lightlvl;
tempstruct->templvl = templvl;
tempstruct->playlist = playlist;
if ( head == NULL ) {
head = tempstruct;
curr = tempstruct;
tempstruct->next = NULL;
} else {
curr->next = tempstruct;
tempstruct->next = NULL;
curr = tempstruct;
}
}
}
fclose (confd);
return head;
} /* scada_mood_config */
/**
*
* scada_play_config() - read config file settings. the mood configuration
* settings are stored in a linked list and the pointer to the head
* is returned.
*
*/
struct playlist *scada_play_config (const char *configfile)
{
FILE *confd;
char buf[BUFSIZE];
struct playlist *head;
struct playlist *curr;
struct playlist *prev;
struct playlist *tempstruct;
struct playlist_node *temp_node;
struct playlist_node *curr_node;
char *temp;
char song[BUFSIZE];
int listnum, found;
head = curr = tempstruct = NULL;
/* open config file */
if ((confd = fopen(configfile, "r")) == NULL) {
printf ("SCADA error: could not open config filename: %s\n", configfile);
return NULL;
}
/* read data from config file */
while (fgets (buf, BUFSIZE, confd) != NULL) {
/* playlist settings */
if ( strncmp (buf, "playlist", 8) == 0) {
sscanf (buf, "playlist %d %s", &listnum, song);
if (( temp = (char *) malloc (strlen (song) + 1) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
exithandl (1);
}
strcpy (temp, song);
/* generate song entry */
if (( temp_node = (struct playlist_node *) malloc (
sizeof (struct playlist_node)) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
exithandl (1);
}
temp_node->song = temp;
temp_node->next = NULL;
/* adding entry */
if ( head == NULL ) {
/* generate new playlist list */
if (( tempstruct = (struct playlist *) malloc (
sizeof (struct playlist)) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
exithandl (1);
}
tempstruct->id = listnum;
tempstruct->list = temp_node;
tempstruct->next = NULL;
head = tempstruct;
curr = tempstruct;
} else {
/* use existing playlist list */
/* check playlist for playlist existing id */
found = 0;
prev = curr = head;
while (curr != NULL) {
if (curr->id == listnum) {
found = 1;
break;
}
prev = curr;
curr = curr->next;
}
/* is play list found? */
if (found == 0) {
/* playlist not found in playlist list. generate one. */
if (( tempstruct = (struct playlist *) malloc (
sizeof (struct playlist)) ) == NULL) {
printf ("SCADA error: memory allocation error\n");
exithandl (1);
}
prev->next = tempstruct;
tempstruct->id = listnum;
tempstruct->list = temp_node;
tempstruct->next = NULL;
} else {
/* playlist found in list */
curr_node = curr->list;
while (curr_node->next != NULL) {
curr_node = curr_node->next;
}
curr_node->next = temp_node;
}
}
}
} /* while */
fclose (confd);
return head;
} /* scada_playlist_config() */
/**
*
* scada_cleanup () - this function does all the housekeeping related
* chores such as clearing up memory.
*
*/
void scada_cleanup (struct moodstruct *mood,
struct playlist *play,
struct modulelist *modules)
{
struct moodstruct *temp;
struct modulelist *tempm;
struct playlist *temp2;
struct playlist_node *temp3;
struct playlist_node *curr;
/* walk the moods */
while (mood != NULL) {
free (mood->moodname);
temp = mood->next;
free (mood);
mood = temp;
}
/* walk all the modules */
while (modules != NULL) {
free (modules->name);
free (modules->path);
tempm = modules->next;
free (modules);
modules = tempm;
}
/* walk the playlists */
while (play != NULL) {
/* move through the songs within playlist */
curr = play->list;
while (curr != NULL) {
free (curr->song);
temp3 = curr->next;
free (curr);
curr = temp3;
}
temp2 = play->next;
free (play);
play = temp2;
}
} /* scada_cleanup () */
TOP
Section : CONTROL.C
/* $Id: control.c,v 1.11 2001/09/25 16:46:06 wyy Exp $ */
/**
*
* control.c
*
* Remote Sensory Control and Data Acquisition Daemon
*
* William Emmanuel S. YU
* Ateneo de Manila University, Philippines
*
* See README for more information.
*
**/
#include "scadad.h"
#include "libscada/libscada.h"
/**
*
* scada_control() - main interactive portion of the SCADA daemon
*
**/
int scada_control (register int newsockfd, int semid)
{
char line[MAXLINE];
char str_operand[BUFSIZE];
char number[BUFSIZE];
char mesg[BUFSIZE];
char inst[BUFSIZE];
int retval, operand, operand2;
struct playlist *playlist;
struct moodstruct *moodlist;
struct scadadstruct *scadad;
/* read the input from the user */
*line = 0;
readnf (newsockfd, line);
/* first do a system synchronization */
if ( system_sync ()) {
syslog (LOG_ERR, "SCADA sync error: synchronization error");
}
/* grab data from memory mapped segment */
sem_wait (semid);
if ( (scadad = shm_read (SHMKEY)) == NULL) {
syslog (LOG_ERR, "SCADA shm error: error reading shared memory");
}
sem_signal (semid);
playlist = scadad->playlist;
moodlist = scadad->moodstruct;
/* define shutdown command */
if ( strncmp (line, "shutdown", 8) == 0) {
sem_wait (semid);
scadad = shm_read (SHMKEY);
sem_signal (semid);
kill (scadad->scadapid, SIGTERM);
exit (0);
}
/* define the send command */
if ( strncmp (line, "send", 4) == 0) {
if ( sscanf (line, "send %" OPERAND_LEN "s %" OPERAND_LEN "s",
number, mesg) != 2) {
writenf (newsockfd, "400 syntax error in send\r\n");
return 1;
}
send_sms (newsockfd, number, mesg);
return 1;
}
/* define the echo command */
if ( strncmp (line, "echo", 4) == 0) {
if ( sscanf (line, "echo %" OPERAND_LEN "s", str_operand) != 1) {
writenf (newsockfd, "400 syntax error in echo\r\n");
return 1;
}
if ( strcmp(str_operand,"") == 0 )
writenf (newsockfd, "400 operand required.\r\n");
else {
#ifdef DEBUG
syslog (LOG_ERR, "SCADA (echo): %s", str_operand);
#endif
writenf (newsockfd, "200 %s\r\n", str_operand);
}
return 1;
}
/* define the show command */
if ( strncmp (line, "show", 4) == 0) {
if ( sscanf (line, "show %" OPERAND_LEN "s", str_operand) != 1) {
writenf (newsockfd, "400 syntax error in show\r\n");
return 1;
}
/* show system command */
if ( strcmp (str_operand, "system") == 0 ) {
if ( status (newsockfd) ) {
writenf (newsockfd, "400 command error.\r\n");
}
return 1;
}
/* if command is not a default command check modules */
if ( exec_show_module (newsockfd, str_operand, &operand, &operand2) ) {
writenf (newsockfd, "300 %s is %s at %d\r\n", str_operand,
(operand!=SERVICE_ON)?((operand==SERVICE_OFF)
?"DEACTIVATED":"ERROR"):"ACTIVATED",
operand2);
return 1;
}
/* unrecoginzed show command */
writenf (newsockfd, "400 unrecognized show command\r\n");
return 1;
}
/* define the stop command */
if ( strncmp (line, "stop", 4) == 0) {
if ( sscanf (line, "stop %" OPERAND_LEN "s", str_operand) != 1) {
writenf (newsockfd, "400 syntax error in stop\r\n");
return 1;
}
/* stop sound command */
if ( strcmp (str_operand, "play") == 0 ) {
if ( scadad->soundstat != SERVICE_ON ) {
writenf (newsockfd, "400 No Audio Device in Use.\r\n");
return 1;
}
if ( play_songlist (newsockfd, 0) ) {
writenf (newsockfd, "400 command error.\r\n");
}
return 1;
}
/* stop aircon */
if ( strcmp (str_operand, "aircon") == 0 ) {
if ( aircon_stop (newsockfd) ) {
writenf (newsockfd, "400 command error.\r\n");
}
return 1;
}
/* if command is not a default command check modules */
if ( exec_set_module (newsockfd, inst, 0, 0) ) {
return 1;
}
/* unrecoginzed stop command */
writenf (newsockfd, "400 unrecognized stop command\r\n");
return 1;
}
/* define the set command */
if ( strncmp (line, "set", 3) == 0) {
retval = sscanf (line, "set %s %d %d", inst, &operand, &operand2);
if (( retval != 2 ) && ( retval !=3 )) {
writenf (newsockfd, "400 syntax error in set\r\n");
return 1;
}
/* define the set play command */
if ( strcmp (inst, "play") == 0) {
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG play: %d", operand);
#endif
if ( play_songlist (newsockfd, operand) ) {
writenf (newsockfd, "400 command error.\r\n");
}
return 1;
}
/* set volume command */
if ( strcmp (inst, "volume") == 0 ) {
if ( mixeradj (newsockfd, SOUND_MIXER_VOLUME, operand, operand2 ) ) {
writenf (newsockfd, "400 command error.\r\n");
}
return 1;
}
/* set aircon */
if ( strcmp (inst, "aircon") == 0 ) {
if ( aircon_start (newsockfd) ) {
writenf (newsockfd, "400 command error.\r\n");
}
return 1;
}
/* set mood command */
if ( strcmp (inst, "mood") == 0 ) {
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG mood: %d", operand);
#endif
if ( mood (newsockfd, operand ) ) {
writenf (newsockfd, "400 command error.\r\n");
}
return 1;
}
/* if command is not a default command check modules */
if ( exec_set_module (newsockfd, inst, operand, operand2) ) {
writenf (newsockfd, "300 %s is %s at %d\r\n", inst,
(operand!=SERVICE_ON)?((operand==SERVICE_OFF)
?"DEACTIVATED":"ERROR"):"ACTIVATED", operand2);
return 1;
}
/* unrecoginzed set command */
writenf (newsockfd, "400 unrecognized set command\r\n");
return 1;
}
/* get help information */
if ((strncmp (line, "help", 4) == 0) ||
(strncmp (line, "?", 1) == 0) ) {
writenf (newsockfd, "300 SCADAD v%s.\r\n",VERSION);
writenf (newsockfd, "300 ----------------------------\r\n");
writenf (newsockfd, "300 help - displays this message\r\n");
writenf (newsockfd, "300 set lights [1/0] [intensity]\r\n");
writenf (newsockfd, "300 set temp [1/0] [intensity]\r\n");
writenf (newsockfd, "300 set mood [n]\r\n");
writenf (newsockfd, "300 set play [play list number]\r\n");
writenf (newsockfd, "300 set aircon 1\r\n");
writenf (newsockfd, "300 show system\r\n");
writenf (newsockfd, "300 stop play\r\n");
writenf (newsockfd, "300 stop lights\r\n");
writenf (newsockfd, "300 stop temp\r\n");
writenf (newsockfd, "300 stop aircon\r\n");
writenf (newsockfd, "300 quit - exits daemon\r\n");
writenf (newsockfd, "300 ----------------------------.\r\n");
return 1;
}
/* exiting the daemon */
if ((strncmp (line, "quit", 4) == 0) ||
(strncmp (line, "exit", 4) == 0) ||
(strncmp (line, "bye", 3) == 0) ) {
return 0;
}
/* error if unrecognized command */
writenf (newsockfd, "400 unrecognized command\r\n");
return 1;
} /* scada_control() */
TOP
Section : MAIN.C
/* $Id: main.c,v 1.26 2001/09/27 08:24:57 wyy Exp $ */
/*
* main.c
*
* Remote Sensory Control and Data Acquisition Daemon
*
* William Emmanuel S. YU
* Ateneo de Manila University, Philippines
*
* See README for more information.
*/
#include "scadad.h"
#include "libparport/libparport.h"
#include "libscada/libscada.h"
/* main function */
int main (int argc, char *argv[])
{
extern char *optarg;
char line[MAXLINE];
char* pidfile;
char* configfile;
int sockfd, newsockfd, clilen, childpid, opt;
int semid, newsemid, scadadconpid, sempp;
int on = 1;
struct scadadstruct *scadad;
struct sockaddr_in cli_addr, serv_addr;
struct moodstruct *moodtable;
struct modulelist *modulelist;
struct playlist *playlist;
char user[BUFSIZE];
char pass[BUFSIZE];
/* check command line options */
if (argc <= 1) {
usage();
return(0);
}
/* process the command line options */
while ((opt = getopt(argc, argv, "f:p:vh")) != -1)
switch (opt) {
case 'v':
printf ("SCADAD v%s Copyright 2001 William Emmanuel S. Yu\n", VERSION);
return (0);
break;
case 'f':
configfile = optarg;
break;
case 'p':
pidfile = optarg;
break;
default:
case 'h':
usage ();
return (0);
break;
}
/* initialize semaphore locking mechanism for shared memory access */
if ( (semid = sem_create (SEMKEY, 1)) < 0) {
syslog (LOG_ERR,"SCADA error: can't open semaphore");
exit (1);
}
/* initialize semaphore locking mechanism for parallel port access */
if ( (sempp = sem_create (LPTKEY, 1)) < 0) {
syslog (LOG_ERR,"SCADA error: can't open semaphore");
exit (1);
}
/* create shared memory segment */
sem_wait (semid);
scadad = shm_create (SHMKEY);
/* initialization routines */
/* set the default values of the control structure */
scadad->soundstat = SERVICE_OFF;
scadad->lightstat = SERVICE_OFF;
scadad->tempstat = SERVICE_OFF;
scadad->airconstat = SERVICE_OFF;
scadad->blink = SERVICE_OFF;
scadad->aircon.status = SERVICE_OFF;
scadad->aircon.main = SERVICE_OFF;
scadad->aircon.compressor = SERVICE_OFF;
scadad->aircon.ready = SERVICE_OFF;
scadad->sms.status = SERVICE_OFF;
scadad->sms.sendpath = NULL;
scadad->env.blink = SERVICE_OFF;
scadad->env.templevel = -1;
scadad->env.tempstat = SERVICE_OFF;
scadad->env.lightlevel = -1;
scadad->env.lightstat = SERVICE_OFF;
scadad->env.lightdevstat = SERVICE_OFF;
scadad->playlistnum = 0;
scadad->moodlevel = 0;
scadad->lightlevel = 50;
scadad->templevel = 25;
scadad->audiopid = 0;
scadad->songindex = 0;
/**
* routines for reading the configuration files. this is not
* the most efficient method since the configuration file is
* read three times. however, this is done because i have
* plans of splitting the configuration file in the future
* the system below makes it easy to do so.
**/
if ( (modulelist = scada_module_config (configfile)) == NULL ) {
printf ("SCADA error: Module Configuration Error.\n");
exithandl (1);
}
if ( (moodtable = scada_mood_config (configfile)) == NULL ) {
printf ("SCADA error: Mood Configuration Error.\n");
exithandl (1);
}
if ( (playlist = scada_play_config (configfile)) == NULL ) {
printf ("SCADA error: Playlist Configuration Error.\n");
exithandl (1);
}
/* set scada structure after configuration */
scadad->modulelist = modulelist;
scadad->moodstruct = moodtable;
scadad->playlist = playlist;
sem_signal (semid);
/* generic configs are read here to prevent loops */
if ( scada_generic_config (configfile) == -1) {
printf ("SCADA error: Generic Configuration Error.\n");
exithandl (1);
}
/* detach daemon and write pid file */
daemon_detach ();
daemon_writePID (pidfile);
/* initialize string pointers */
*user = *pass = 0;
/* before anything else got to catch the exit signals */
(void) signal (SIGHUP, exithandl);
(void) signal (SIGINT, exithandl);
(void) signal (SIGTERM, exithandl);
(void) signal (SIGQUIT, exithandl);
/* the SIGCHLD is caught to clean up zombies */
(void) signal (SIGCHLD, sig_child);
/* openning syslog for logging writing initial message */
openlog ("scadad", LOG_PID, LOG_LOCAL4);
/* openning a tcp socket */
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
syslog (LOG_ERR, "SCADA error: cannot open stream socket");
close (sockfd);
exit (1);
}
/**
* bind ourselves to our local address so that client can
* sent messeges to us
**/
bzero ((char*) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl (INADDR_ANY);
serv_addr.sin_port = htons (SERV_TCP_PORT);
/**
* set the socket to reuse the address
* i am not very sure about the consequences of using this
* function to allow immediate reconnects. it seems to block
* existing requests gracefully.
**/
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
/* actual bind command */
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
syslog (LOG_ERR, "SCADA error: unable to bind to port");
close (sockfd);
exit (1);
}
/* get the socket file descriptor and pid for proper system shutdown */
sem_wait(semid);
scadad->sockfd = sockfd;
scadad->scadapid = getpid ();
sem_signal(semid);
/**
* create a daemon control process. this code was written to
* allow for unattended hardware software interaction. this
* process can be killed by sending a SIGHUP.
**/
if ( (scadadconpid = fork ()) < 0) {
syslog (LOG_ERR, "SCADA error: unable to spawn control process");
} else if (scadadconpid == 0) {
/* restore signals to default values */
(void) signal (SIGHUP, exit);
(void) signal (SIGINT, exit);
(void) signal (SIGTERM, exit);
(void) signal (SIGQUIT, exit);
(void) signal (SIGCHLD, SIG_IGN);
/* set the controlpid member of the control structure */
semid = sem_open (SEMKEY);
sempp = sem_open (LPTKEY);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->controlpid = getpid();
sem_signal (semid);
/* get control of the parallel port */
sem_wait (sempp);
if ( pin_init_user(LPT1) ) {
syslog (LOG_ERR, "SCADA error: unable to access parallel port");
sem_wait (semid);
scadad = shm_read (SHMKEY);
sem_signal (semid);
kill (scadad->scadapid, SIGTERM);
exit (0);
}
/* configure parallel port */
pin_output_mode ( LP_PIN14 | LP_PIN16 | LP_PIN17 );
/* clear data pins by default */
pin_set_data (0, LP_DATA_PINS, 0, 1, 1);
sem_signal (sempp);
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (control-out): Clearing Output Pins");
#endif
/* place control routines here */
while (1) {
int status, tmplevel, userlevel, temp, devstat, eblink, blink;
int delay = POLLDELAY;
int amain, compressor, lever, ready, lightstat;
/**
* place routines for polling devices
* temperature and light sensors must
* be read here. scada structure is
* set after reading. check sensors here.
**/
sem_wait (sempp);
/**
* temperature sensor code. sends the 100 code to the
* control lines of the parallel port to signal and input.
* a small delay is placed to prevent a race condition.
**/
/* setting temperature sensors */
tmplevel = pin_get_data ( 1, 0, 0 );
tmplevel = ((tmplevel * 50) / 255);
if ((tmplevel < 5) || (tmplevel > 45)) {
/* retain previous values if error occurs */
sem_wait (semid);
tmplevel = scadad->env.templevel;
sem_signal (semid);
status = SERVICE_ERR;
} else status = SERVICE_ON;
/* store in scadad structure */
semid = sem_open (SEMKEY);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->env.templevel = tmplevel;
scadad->env.tempstat = status;
userlevel = scadad->templevel;
lever = scadad->airconstat;
ready = scadad->aircon.ready;
compressor = scadad->aircon.compressor;
sem_signal (semid);
/**
* adjust compressor settings for temperature variations from
* the preconfigured temperature. delay is set in the header
* file. if temperature is below user defined level then the
* compressor is switched on. if the temperature is above the
* user defined level then the compressor is switched off.
* this routine does not recognize time delays between the
* compressors switch on and off. this should be trapped by
* hardware. signals should be ignored if not within threshold.
**/
if ((tmplevel < userlevel - TEMPVARIATION) && (status != SERVICE_ERR)
&& (lever == SERVICE_ON) && (ready == SERVICE_ON)
&& (compressor == SERVICE_ON))
aircon_set (1, 0);
if ((tmplevel > userlevel + TEMPVARIATION) && (status != SERVICE_ERR)
&& (lever == SERVICE_ON) && (ready == SERVICE_ON)
&& (compressor == SERVICE_OFF))
aircon_set (1, 1);
/**
* light sensor code. sends the 001 code to the
* control lines of the parallel port to signal and input.
* a small delay is placed to prevent a race condition.
**/
/* setting light sensors */
tmplevel = pin_get_data ( 0, 0, 0 );
tmplevel = ((tmplevel * 50) / 255);
if ((tmplevel > 49)) {
/* retain previous values if error occurs */
sem_wait (semid);
tmplevel = scadad->env.lightlevel;
sem_signal (semid);
status = SERVICE_ERR;
} else status = SERVICE_ON;
/* store in scadad structure */
semid = sem_open (SEMKEY);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->env.lightlevel = tmplevel;
scadad->env.lightstat = status;
userlevel = scadad->lightlevel;
lightstat = scadad->lightstat;
devstat = scadad->env.lightdevstat;
sem_signal (semid);
/**
* code for controlling the light sensivity. right now the range
* of the light values if 6 bits therefore we have level of 0 to 64
* that can be utilized to setting light levels. since, the code
* utilized a base of 50 then 64 is normalized to 50.
**/
/* turn off the lights */
if ((lightstat == SERVICE_OFF)
&& (devstat == SERVICE_ON)) {
pin_set_level (0, 0, 1, 1);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->env.lightdevstat = SERVICE_OFF;
devstat = SERVICE_OFF;
sem_signal (semid);
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (control-lights): turn off %d %d ",
lightstat, devstat);
#endif
}
/* light adjustment code */
if ((tmplevel < userlevel - LIGHTVARIATION)
&& (tmplevel > userlevel + LIGHTVARIATION)
&& (status == SERVICE_ON)
&& (devstat == SERVICE_ON)) {
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (control-lights): adjusting %d %d",
tmplevel, userlevel);
#endif
temp = (tmplevel * 63) / 50;
pin_set_level (temp, 0, 1, 1);
}
/* turn on the lights */
if ((lightstat == SERVICE_ON)
&& (devstat == SERVICE_OFF)) {
temp = (userlevel * 63) / 50;
pin_set_level (temp, 0, 1, 1);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->env.lightdevstat = SERVICE_ON;
devstat = SERVICE_ON;
sem_signal (semid);
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (control-lights): turn on %d %d - %d",
lightstat, devstat, temp);
#endif
}
/**
* blinker code
**/
sem_wait (semid);
scadad = shm_read (SHMKEY);
eblink = scadad->env.blink;
blink = scadad->blink;
sem_signal (semid);
if ((eblink == SERVICE_ON) && (blink == SERVICE_ON)) {
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (control-lights): blink off");
#endif
pin_set_level (userlevel, 0, 1, 1);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->env.blink = SERVICE_OFF;
sem_signal (semid);
}
if ((eblink == SERVICE_OFF) && (blink == SERVICE_ON)) {
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (control-lights): blink on");
#endif
pin_set_level (0, 0, 1, 1);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->env.blink = SERVICE_ON;
sem_signal (semid);
}
/**
* routine for starting the aircon if still off
* the next routine is to check if the aircon is on
**/
semid = sem_open (SEMKEY);
sem_wait (semid);
scadad = shm_read (SHMKEY);
amain = scadad->aircon.main;
status = scadad->airconstat;
ready = scadad->aircon.ready;
sem_signal (semid);
if ((amain == SERVICE_OFF)
&& (status == SERVICE_ON)) {
low_aircon_start();
delay = 0;
}
if ((amain == SERVICE_ON)
&& (status == SERVICE_OFF)) {
low_aircon_stop();
delay = 0;
}
sem_signal (sempp);
sleep(delay);
sem_wait (sempp);
/**
* blinker code
**/
sem_wait (semid);
scadad = shm_read (SHMKEY);
eblink = scadad->env.blink;
blink = scadad->blink;
sem_signal (semid);
if ((eblink == SERVICE_ON) && (blink == SERVICE_ON)) {
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (control-lights): blink off");
#endif
pin_set_level (userlevel, 0, 1, 1);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->env.blink = SERVICE_OFF;
sem_signal (semid);
}
if ((eblink == SERVICE_OFF) && (blink == SERVICE_ON)) {
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (control-lights): blink on");
#endif
pin_set_level (0, 0, 1, 1);
sem_wait (semid);
scadad = shm_read (SHMKEY);
scadad->env.blink = SERVICE_ON;
sem_signal (semid);
}
sem_signal (sempp);
}
exit(0);
} /* end daemon control process */
syslog (LOG_INFO, "SCADA v%s Daemon Started", VERSION);
/* let our daemon listen for incoming connections */
listen(sockfd, 5);
for ( ; ; ) {
/* wait for a connection */
clilen = sizeof (cli_addr);
newsockfd = accept (sockfd, (struct sockaddr *) &cli_addr, &clilen);
newsemid = sem_open (SEMKEY);
/* error getting connection */
if (newsockfd < 0)
syslog (LOG_ERR, "SCADA error: accept error");
/* spawn new process for connection */
if ( (childpid = fork ()) < 0)
syslog (LOG_ERR, "SCADA error: server fork error");
else if (childpid == 0) {
/* close parent's socket and reset child signals */
close (sockfd);
(void) signal (SIGCHLD, SIG_IGN);
(void) signal (SIGHUP, exit);
(void) signal (SIGINT, exit);
(void) signal (SIGTERM, exit);
(void) signal (SIGQUIT, exit);
/* display welcome message */
writenf (newsockfd, "100 SCADAD v%s.\r\n", VERSION);
/**
* authentication portion of the system. authenticaion
* is defined during compile time. there are a few available
* authentication modules with this system. replace
* the code for the authentication module with the desired
* code. sorry no time to make it modular.
**/
/* get username */
readnf (newsockfd, line);
sscanf (line, "user %" MAX_LEN_USERNAME "s", user) ;
if (strlen (user) == 0) {
writenf (newsockfd, "400 Username required\r\n");
writenf (newsockfd, "200 Bye.\r\n");
exit (1);
}
/* get password */
writenf (newsockfd, "Enter Password.\r\n");
readnf (newsockfd, line);
sscanf (line, "pass %" MAX_LEN_PASS "s", pass);
if ((strlen(pass) > 126) || (strlen(pass) == 0) ) {
writenf (newsockfd, "500 Password required\r\n");
writenf (newsockfd, "200 Bye.\r\n");
exit (1);
}
/* authentication section */
if (scada_authenticate(newsockfd, user, pass) == 0 ) {
/* interactive section of the program */
*line = 0;
/**
* this is the main scada interaction routine. this
* will exit when the user desires to quite or
* terminate the system
**/
while ( scada_control (newsockfd, newsemid) );
} else {
writenf (newsockfd, "500 Authentication Failure.\r\n");
}
writenf (newsockfd, "200 Bye.\r\n");
/* added to remote waiting children */
close (newsockfd);
exit (0);
}
/* mother process has no need for the client file descriptor */
close (newsockfd);
}
/* clean up functions */
exithandl (0);
}
TOP
Section : MODULE.C
/* $Id: module.c,v 1.5 2001/09/23 14:43:46 wyy Exp $ */
/*
* module.c
*
* Remote Sensory Control and Data Acquisition Daemon
*
* William Emmanuel S. YU
* Ateneo de Manila University, Philippines
*
* See README for more information.
*/
#include "scadad.h"
#include "dlfcn.h"
#include "libscada/libscada.h"
/* function declaration for dynamically loadable function */
typedef int (*dynfunc_t) (int, int);
typedef int (*dynfunc2_t) (int*, int*);
/**
*
* exec_sys_module () - code used to show loadable modules status
*
**/
int exec_sys_module (char* inst,
int *oper, int *oper2){
struct scadadstruct *scadad;
struct modulelist *modulelist;
int semid;
char function[BUFSIZE];
char *libname;
void *ptr = NULL;
dynfunc2_t func = NULL;
/* grab data from memory mapped segment */
semid = sem_open (SEMKEY);
sem_wait (semid);
scadad = shm_read (SHMKEY);
modulelist = scadad->modulelist;
sem_signal (semid);
/* which module */
while ( (modulelist != NULL) && (strcmp (modulelist->name,inst) ) ) {
modulelist = modulelist->next;
}
if (modulelist != NULL) {
strcpy(function,"sys");
strcat(function, modulelist->name);
libname = modulelist->path;
/* dynamically load library */
if ((ptr=dlopen(libname, RTLD_LAZY))==NULL){
syslog (LOG_ERR, "400 dlopen(%s)->%s\r\n", libname, dlerror());
return 1;
}
/* dynamically load function */
if ((func = (dynfunc2_t)dlsym(ptr, function))==NULL){
syslog (LOG_ERR, "400 dlopen(%s)->%s\r\n", function, dlerror());
return 1;
}
/* execute the module */
if ( (*func) (oper, oper2 ) ) {
syslog (LOG_ERR, "SCADA error: critical system %s error", inst);
return 1;
}
dlclose (ptr);
sem_wait(semid);
modulelist->status = *oper;
modulelist->level = *oper2;
sem_signal(semid);
return 1;
}
return 0;
}
/**
*
* exec_show_module () - code used to show loadable modules status
*
**/
int exec_show_module (register int newsockfd, char* inst,
int *oper, int *oper2){
struct scadadstruct *scadad;
struct modulelist *modulelist;
int semid;
char function[BUFSIZE];
char *libname;
void *ptr = NULL;
dynfunc2_t func = NULL;
/* grab data from memory mapped segment */
semid = sem_open (SEMKEY);
sem_wait (semid);
scadad = shm_read (SHMKEY);
modulelist = scadad->modulelist;
sem_signal (semid);
/* which module */
while ( (modulelist != NULL) && (strcmp (modulelist->name,inst) ) ) {
modulelist = modulelist->next;
}
if (modulelist != NULL) {
strcpy(function,"s");
strcat(function, modulelist->name);
libname = modulelist->path;
/* dynamically load library */
if ((ptr=dlopen(libname, RTLD_LAZY))==NULL){
writenf (newsockfd, "400 dlopen(%s)->%s\r\n", libname, dlerror());
return 1;
}
/* dynamically load function */
if ((func = (dynfunc2_t)dlsym(ptr, function))==NULL){
writenf (newsockfd, "400 dlopen(%s)->%s\r\n", function, dlerror());
return 1;
}
/* execute the module */
if ( (*func) (oper, oper2 ) ) {
writenf (newsockfd, "400 %s command error.\r\n", inst);
return 1;
}
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG %s: %d %d", inst, *oper, *oper2);
#endif
dlclose (ptr);
sem_wait(semid);
modulelist->status = *oper;
modulelist->level = *oper2;
sem_signal(semid);
return 1;
}
return 0;
}
/**
*
* exec_set_module () - code used to execute loadable modules
*
**/
int exec_set_module (register int newsockfd, char* inst, int oper, int oper2){
struct scadadstruct *scadad;
struct modulelist *modulelist;
int semid;
char *function;
char *libname;
void *ptr = NULL;
dynfunc_t func = NULL;
/* grab data from memory mapped segment */
semid = sem_open (SEMKEY);
sem_wait (semid);
scadad = shm_read (SHMKEY);
modulelist = scadad->modulelist;
sem_signal (semid);
/* which module */
while ( (modulelist != NULL) && (strcmp (modulelist->name,inst) ) ) {
modulelist = modulelist->next;
}
if (modulelist != NULL) {
function = modulelist->name;
libname = modulelist->path;
/* dynamically load library */
if ((ptr=dlopen(libname, RTLD_LAZY))==NULL){
writenf (newsockfd, "400 dlopen(%s)->%s\r\n", libname, dlerror());
return 1;
}
/* dynamically load function */
if ((func = (dynfunc_t)dlsym(ptr, function))==NULL){
writenf (newsockfd, "400 dlopen(%s)->%s\r\n", function, dlerror());
return 1;
}
/* execute the module */
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG %s: %d %d", inst, oper, oper2);
#endif
if ( (*func) (oper, oper2 ) ) {
writenf (newsockfd, "400 %s command error.\r\n", inst);
dlclose (ptr);
return 1;
}
dlclose (ptr);
return 1;
}
return 0;
}
TOP
Section : PAM.C
/* $Id: pam.c,v 1.2 2001/09/11 08:41:27 wyy Exp $ */
/*
* pam.c
*
* Remote Sensory Control and Data Acquisition Daemon
*
* William Emmanuel S. YU
* Ateneo de Manila University, Philippines
*
* See README for more information.
*/
#include "scadad.h"
#include
#include
/* function declaration */
int scada_conv (int, const struct pam_message **, struct pam_response **, void *);
int scada_pam_auth (void *);
/**
*
* scada_authenticate() - function call to authenticate scada daemon using
* linux password authentication modules
*
*/
int scada_authenticate (register int newsockfd, char* user, char* pass)
{
struct pam_data *app_data;
int retval;
/* initialize and load values to the app_data structure */
app_data = (struct pam_data *) malloc (sizeof(struct pam_data));
bzero (app_data, sizeof (struct pam_data));
app_data->user = user;
app_data->pass = pass;
app_data->fd = newsockfd;
retval = scada_pam_auth ( (void *)app_data );
free(app_data);
return retval;
} /* scada_authenticate() */
/**
*
* scada_pam_auth() - actual authentication function
*
*/
int scada_pam_auth (void *app_data)
{
pam_handle_t *pamh=NULL;
int retval;
int sockfd;
/* converstation structure */
struct pam_conv conv = {
scada_conv,
app_data
};
sockfd = ((struct pam_data *)app_data)->fd;
retval = pam_start("scadad", ((struct pam_data *)app_data)->user,
&conv, &pamh);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0);
/* This is where we have been authorized or not. */
if (retval == PAM_SUCCESS) {
writenf (sockfd, "200 Authenticated.\r\n");
} else {
writenf (sockfd, "500 Not Authenticated.\r\n");
}
if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
pamh = NULL;
writenf (sockfd, "500 Failed to release authenticator\n");
exit(1);
}
return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
} /* scada_pam_auth() */
/**
*
* scada_conv() - scada conversation function for interacting with PAM
* libraries
*
*/
int scada_conv (int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int i;
struct pam_response *r = calloc(num_msg, sizeof(struct pam_response));
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (PAM) message: %d", msg[0]->msg_style);
#endif
if (num_msg <= 0)
return(PAM_CONV_ERR);
if (r == NULL)
return(PAM_CONV_ERR);
for(i=0; i < num_msg; i++) {
if(msg[i]->msg_style == PAM_ERROR_MSG) {
syslog(LOG_ERR, "SCADA PAM error: %s", msg[i]->msg);
syslog(LOG_ERR, "Failed attempt to change password for %s",
((struct pam_data *)appdata_ptr)->user);
exit(1);
}
r[i].resp_retcode = 0;
if(msg[i]->msg_style == PAM_PROMPT_ECHO_OFF ||
msg[i]->msg_style == PAM_PROMPT_ECHO_ON)
{
r[i].resp = strdup( ((struct pam_data *)appdata_ptr)->pass);
} else {
r[i].resp = strdup("");
}
}
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (PAM) response: %d", r[i].resp_retcode);
#endif
*resp = r;
return PAM_SUCCESS;
} /* scada_conv() */
TOP
Section : PASSWD.C
/* $Id: passwd.c,v 1.2 2001/09/11 08:41:27 wyy Exp $ */
/*
* passwd.c
*
* Remote Sensory Control and Data Acquisition Daemon
*
* William Emmanuel S. YU
* Ateneo de Manila University, Philippines
*
* See README for more information.
*/
#include "scadad.h"
#define _XOPEN_SOURCE
#include
#include
#include
/**
*
* scada_authenticate() - function call to authenticate scada daemon using
* linux password authentication modules
*
*/
int scada_authenticate (register int newsockfd, char* user, char* pass)
{
struct passwd *pwd;
if ( (pwd = getpwnam(user)) == NULL) {
syslog (LOG_ERR, "SCADA passwd error: auth error for user %s", user);
writenf (newsockfd, "500 Not Authenticated.\r\n");
return 1;
}
#ifdef DEBUG
syslog (LOG_ERR, "DEBUG (passwd): %s %s", user, pass);
syslog (LOG_ERR, "DEBUG (passwd): %s %s", pwd->pw_passwd,
(char *) crypt (pass, pwd->pw_passwd) );
#endif
if ( strcmp( pwd->pw_passwd, (char *) crypt (pass, pwd->pw_passwd) ) ) {
writenf (newsockfd, "500 Authenticated.\r\n");
return 0;
}
syslog (LOG_ERR, "SCADA passwd error: auth error for user %s", user);
writenf (newsockfd, "500 Not Authenticated.\r\n");
return 1;
} /* scada_authenticate() */
TOP
Section : UTIL.C
/* $Id: util.c,v 1.4 2001/09/20 09:44:10 wyy Exp $ */
/*
* util.c
*
* Remote Sensory Control and Data Acquisition Daemon
*
* William Emmanuel S. YU
* Ateneo de Manila University, Philippines
*
* See README for more information.
*/
#include "scadad.h"
#include "libscada/libscada.h"
#include
/**
* usage() - displays help file
*/
void usage()
{
printf ("SCADAD v%s Copyright 2001 William Emmanuel S. Yu\n", VERSION);
printf("Usage: scadad [options]\n");
printf("-f \t\tset location of config file\n");
printf("-p \t\tset location of pid file\n");
printf("-v\t\t\tdisplays version information\n");
printf("-h\t\t\tdisplays this help info\n");
printf("\n");
printf("For bugs email: william.s.yu@ieee.org\n");
} /* usage() */
/**
* exithandl() - function that is called when a kill signal is received
*/
void exithandl(int sgn)
{
int semid, stat;
struct scadadstruct* scadad;
(void) signal (SIGCHLD, SIG_IGN);
semid = sem_open (SEMKEY);
sem_wait (semid);
if ( (scadad = shm_read (SHMKEY)) == NULL) {
syslog (LOG_ERR, "SCADA shm error: error reading shared memory");
}
sem_signal (semid);
/* kill audio process is alive */
if ( scadad->soundstat == SERVICE_ON ) {
kill (scadad->audiopid, SIGHUP);
}
/* kill aircon is still open */
if (scadad->aircon.main == SERVICE_ON) {
low_aircon_stop();
}
/* clean-up configuration structures */
scada_cleanup (scadad->moodstruct, scadad->playlist, scadad->modulelist);
/* kill control process */
kill (scadad->controlpid, SIGHUP);
wait (&stat);
/* release socket */
close (scadad->sockfd);
/* releasing shared memory space */
/* add delay to prevent race condition */
sleep(1);
sem_wait(semid);
if ( shm_remove (SHMKEY) ) {
syslog (LOG_ERR, "SCADA shm error: error releasing shared memory");
}
sem_signal(semid);
sem_rm (semid);
semid = sem_open (LPTKEY);
sem_rm (semid);
syslog (LOG_INFO, "SCADA v%s Daemon Stopped", VERSION);
closelog ();
exit (sgn);
}
/**
* sig_child() - signal handlers for catching dead children processes
*/
void sig_child(int sgn)
{
int stat, errno_save;
pid_t pid;
errno_save = errno;
if ( (pid = waitpid(0, &stat, 0)) <= 0) {
syslog (LOG_ERR, "SCADA signal error: waitpid error");
}
errno = errno_save;
return;
} /* sig_child() */
/**
* daemon_detach() - helper functions to detach daemon from controlling
* terminal
*/
void daemon_detach()
{
int x;
int pgrp;
chdir ("/");
/* parent quits; error quits; child continues: */
x = fork ();
if ( x > 0 )
exit (0);
else if ( x == -1 ) {
syslog (LOG_ERR, "SCADA error: server fork error");
exit (-1);
}
/* Make sure we don't prevent any directory removals or
filesystem unmounts. */
chdir ("/");
pgrp = setsid ();
if (pgrp == -1) {
syslog (LOG_ERR, "SCADA error: cannot detach from controlling terminal");
exit (-2);
}
}
/*
* daemon_writePID() - lets the daemon write its PID file
*
*/
void daemon_writePID(const char *pidFilePath)
{
FILE *pidf;
pidf = fopen(pidFilePath,"w");
if( pidf==NULL )
syslog (LOG_INFO,"Could not open PID file %s",pidFilePath);
else
{
fprintf(pidf,"%ld\n",(long)getpid());
fclose(pidf);
}
syslog (LOG_INFO,"Server running in PID %ld",(long)(getpid()));
}
/*
* writenf() - write to a file descriptor but a little smarter
*/
void writenf (register int fd, const char* fmt, ...)
{
char line[MAXLINE], *ptr;
int n;
va_list args;
ptr = line;
va_start (args, fmt);
vsprintf (ptr, fmt, args);
ptr += strlen (ptr);
va_end (args);
n = strlen (line);
if (n >= MAXLINE)
n = MAXLINE;
writen(fd, line, n);
}
/*
* readnf() - reading from a file descriptor but a bit smarter
*/
void readnf (register int fd, char *line)
{
int n;
n = readline(fd, line, MAXLINE);
if (n == 0)
return;
else if (n < 0)
syslog(LOG_ERR, "str_echo: readline error");
}
/*
* readn() - reads nbytes of characters from file descriptor fd and
* stores then to a location pointed to by ptr. replacement for read().
* returns the number of bytes read. if not returns -1.
*/
int readn (register int fd, register char *ptr, register int nbytes)
{
int nleft, nread;
nleft = nbytes;
while (nleft > 0) {
nread = read (fd, ptr, nleft);
if (nread < 0)
return (nread);
else if (nread==0)
break;
nleft -= nread;
ptr += nread;
}
return (nbytes - nleft);
} /* readn() */
/*
* writen() - writes nbytes to a location pointed to by a file descriptor
* fd. replacement for write(). function returns the length of bytes written
* if successful if not it returns -1.
*/
int writen (register int fd, register char *ptr, register int nbytes)
{
int nleft, nwritten;
nleft = nbytes;
while (nleft > 0) {
nwritten = write (fd, ptr, nleft);
if (nwritten <= 0)
return (nwritten);
nleft -= nwritten;
ptr += nwritten;
}
return (nbytes - nleft);
} /* writen() */
/*
* readline() - read an entire line from a file descriptor until a newline.
* functions returns the number of characters read but not including the
* null character.
*/
int readline(register int fd, register char *ptr, register int maxlen)
{
int n, rc;
char c;
for (n = 1; n < maxlen; n++) {
if ((rc = read(fd, &c, 1)) == 1) {
*ptr++ = c;
if (c == '\n') break;
} else if (rc == 0) {
if (n == 1)
return (0);
else
break;
} else
return (-1);
}
*ptr=0;
return (n);
} /* readline() */
/*
* str_echo() - reads a stream sockets one line at a time, and
* writes each line back to the sender.
*/
void str_echo(int sockfd)
{
int n;
char line[MAXLINE];
for ( ; ; ) {
n = readline(sockfd, line, MAXLINE);
if (n == 0)
return;
else if (n < 0)
syslog(LOG_ERR, "str_echo: readline error");
if (writen(sockfd, line, n) != n)
syslog(LOG_ERR, "str_echo: writen error");
}
} /* str_echo() */
TOP
Section : SCADAD.H
/* $Id: scadad.h,v 1.23 2001/09/30 14:23:44 wyy Exp $ */
/*
* scadad.h
*
* Remote Sensory Control and Data Acquisition Daemon
*
* William Emmanuel S. YU
* Ateneo de Manila University, Philippines
*
* See README for more information.
*/
/* common defines */
#define VERSION "1.0BETA135-5"
#define MIXER_DEVICE "/dev/mixer"
#define AIRCONDELAY 10 /* must be set to three minutes delay
for switching on and off aircon. maybe damage unit. */
#define POLLDELAY 9 /* set polling delay for control
subsystem to 30 seconds */
#define TEMPVARIATION 1 /* temperature is allowed to make
a one degree variation */
#define LIGHTVARIATION 5 /* lights are allowed to make
a five level variation */
#define MAXLINE 512
#define SERV_UDP_PORT 6543
#define SERV_TCP_PORT 6543
#define BUFSIZE 128
#define OPERAND_LEN "126"
#define MAX_LEN_USERNAME "16"
#define MAX_LEN_PASS "126"
#define SEMKEY ((key_t) 11980L)
#define SHMKEY ((key_t) 18911L)
#define LPTKEY ((key_t) 18188L)
#define AIRKEY ((key_t) 22299L)
/* some SCADAD defines */
#define SERVICE_UNDEF -1
#define SERVICE_ON 1
#define SERVICE_OFF 0
#define SERVICE_ERR -2
/* common include files */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "libunix/semaph.h"
#include "libunix/shm.h"
/* pam structure declaration */
struct pam_data {
char *user;
char *pass;
int fd;
};
/* scadad status and control structure */
struct dipole {
short int left;
short int right;
};
struct airconstruct {
short int status;
short int compressor;
short int main;
short int ready;
int temp;
};
struct env {
int templevel;
int lightlevel;
short int lightstat;
short int lightdevstat;
short int tempstat;
short int blink;
};
struct sms {
int status;
char *sendpath;
char *number;
};
struct scadadstruct {
int scadapid;
int audiopid;
int controlpid;
int sockfd;
short int soundstat;
short int lightstat;
short int tempstat;
short int airconstat;
short int blink;
int playlistnum;
int moodlevel;
int lightlevel;
int templevel;
struct airconstruct aircon;
struct env env;
struct sms sms;
struct dipole mixer[SOUND_MIXER_NRDEVICES];
struct moodstruct *moodstruct;
struct playlist *playlist;
struct modulelist *modulelist;
int songindex;
};
/* mood structure */
struct moodstruct {
char *moodname;
int moodnum;
int lightlvl;
int templvl;
int playlist;
struct moodstruct *next;
};
/* playlist structure */
struct playlist {
int id;
struct playlist_node* list;
struct playlist *next;
};
/* pluggable modules */
struct modulelist {
char *name;
char *path;
int status;
int level;
struct modulelist *next;
};
/* playlist_node structure */
struct playlist_node {
char *song;
struct playlist_node* next;
};
/* function declaration section */
/* signal handling functions */
void exithandl (int);
void sig_child (int);
/* config file related functions */
int scada_generic_config (const char *);
struct moodstruct *scada_mood_config (const char *);
struct playlist *scada_play_config (const char *);
struct modulelist *scada_module_config (const char *);
void scada_cleanup (struct moodstruct *, struct playlist *,
struct modulelist *);
/* daemon helper functions */
void daemon_detach ();
void daemon_writePID (const char*);
/* network helper functions */
int readn (register int, register char *, register int);
int writen (register int, register char *, register int);
int readline(register int, register char *, register int);
void str_echo(int);
void readnf (register int, char*);
void writenf (register int, const char*, ...);
/* authentication function */
int scada_authenticate(register int, char*, char*);
/* control and interaction functions */
int scada_control (register int, int);
int exec_set_module (register int, char*, int, int);
int exec_show_module (register int, char*, int*, int*);
int exec_sys_module (char*, int*, int*);
/* misc helper functions */
void usage ();
|