Hallo an Alle,
nachdem ich in diesem Forum schon einmal mein erstes Projekt sms2action vorgestellt habe, kommt nun der Nachfolger: messag2action.
Warum ein Nachfolger zu sms2action? message2action kann nun nicht nur SMS verarbeiten sondern auch den Betreff von Mails, um Aktionen auf den Pi auszulösen. Es ist also etwas allgemeingültiger gehalten betreff den Nachrichten, die verarbeitet werden können.
Um Mails regelmässig abzuholen, benutze ich fetchmail und lasse die Mails als Textdatei in einem Verzeichnis ablegen. Wenn eine Mail rausgehen soll, wird diese in einem anderen Verzeichnis abgelegt und ich lasse diese dann mit ssmtp versenden.
Beide Pakete (fetchmail und ssmtp) muss man also selbst installieren und einrichten. Mit entsprechenden service- und timer-Dateien kann ich systemd nutzen, um regelmässig Mails abzuholen und zu versendende Mails auch zu verschicken. Beispieldateien für systemd habe ich in dem Archiv mit abgelegt.
Ich nutze eine Mailadresse, die nur für den Zweck eingerichtet wurde, damit mein Pi von dort Kommandos bekommt und Antworten über diese Mailadresse an den eigentlichen Absender zurücksendet.
Soll heißen, ich kann zum Beispiel von einem anderem Account aus eine Status-Anfrage an den Pi senden und ich erhalte auch an die Mailadresse die Antwort zurück, von der ich gesendet habe.
Über die ini-Datei kann ich 10 gültige Mailadressen angeben, von denen aus der Pi Anfragen akzeptiert.
Es gibt eine recht ausführliche Dokumentation in Text- und PDF-Format, in der ich alle Eigenschaften von message2action beschrieben habe. Die Textdatei habe ich hier mit eingebaut.
Auch den Quellcode in C habe ich hier eingebaut:
//************************************************************************************************************************************************************
// message2action, version : see variable version_of_program
// by Fuseless-Project
//
// This program is free software. Feel free to redistribute it and/or modify it under the terms of the GNU General Public License as published by the
// Free Software Foundation. This is valid for version 2 of the license or (at your option) any later version.
// This program was setup for my own usages but I'm sure that minimum 1 other user will find it as useful for his own purposes. I've set it up
// WITHOUT ANY WARRANTY. See the GNU General Public License for more details: http://www.gnu.org/licenses/gpl.txt
//************************************************************************************************************************************************************
#define DEVSTAGE // we define here that we are in developping stage and not in production stage. In order to switch to production stage comment this out
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <termios.h>
#include <pthread.h>
#include <linux/reboot.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/reboot.h>
#include <sys/select.h>
// following section defines global variables
#define MAX_CONFIG_FILE_SIZE 8192 // filesize of configfile must not exceed this amount of bytes
#define MAX_CHARS_PER_LINE_CONFIGFILE 200 // maximum 200 charackters per line in configfile; this value is also used for maximum length of values in ini-file
#define MAX_CHARS_PER_LINE_LOGFILE 200 // maximum 200 charackters per line in logfile
#define MAX_NUMBER_OF_PARAMETERS_CONFIGFILE 200 // maximum 200 values in configfile
#define MESSAGE_TYPE_SMS 0 // the type of message is SMS
#define MESSAGE_TYPE_MAIL 1 // the type of message is mail
#define MESSAGE_TYPE_PUSHBULLET 2 // the type of message is pushbullet
#define FALSE 0
#define TRUE 1
// define a list of errorcodes which can be used in functions:
#define NOERROR 0
#define CONFIG_FILE_READ_ERROR 1 // something wrong with reading the config-file
#define CONFIGFILESIZEERROR 2 // config-file is too large
#define CONFIG_FILE_MAC_ERROR 3 // MAC-adress in configfile is not valid for example 'ZE'
#define CONFIG_FILE_MAX_LOGFILE_ERROR 4 // value for maxsize of logfile is invalid
#define CONFIG_FILE_WAIT_TIME_NEXT_MESSAGE_ERROR 5 // value for wait-time for next message is
#define CONFIG_FILE_CELL_PHONE_STRING_ERROR 6 // something wrong with cell-phone number: does not contain '0' to '9'
#define CONFIG_FILE_CELL_PHONE_FOUND_ERROR 7 // we do not have any valid cell-phone in ini-file
#define CONFIG_FILE_PATH_LOGFILE_ERROR 8 // path to logfile is not correct
#define CONFIG_FILE_IP_OR_HOST_MISSING_ERROR 9 // behind MAC-address no ip-address or hostname specified
#define CONFIG_FILE_PATH_INCOMING_SMS_ERROR 10 // the path for incoming SMS is not valid
#define CONFIG_FILE_PATH_OUTGOING_SMS_ERROR 11 // the path for outgoing SMS is not valid
#define CONFIG_FILE_PATH_PROCESSED_SMS_ERROR 12 // path for processed SMS is not valid
#define CONFIG_FILE_SMS_PID_FILE_ERROR 13 // file for saving PID for SMS is not valid
#define CONFIG_FILE_PATH_INCOMING_MAIL_ERROR 14 // the path for incoming SMS is not valid
#define CONFIG_FILE_PATH_OUTGOING_MAIL_ERROR 15 // the path for outgoing SMS is not valid
#define CONFIG_FILE_PATH_PROCESSED_MAIL_ERROR 16 // path for processed SMS is not valid
#define CONFIG_FILE_MAIL_PID_FILE_ERROR 17 // file for saving PID for mail is not valid
#define CONFIG_FILE_CHECK_ONLINE_WAIT_TIME_ERROR 18 // the value for the waittime after sending WOL is not valid
#define CONFIG_FILE_FULLPATH_SSMTP_ERROR 19 // the program ssmtp is not there as specified in ini-file
#define KEYBOARD_THREAD_ERROR 20 // the thread could not be started to listen to keyboard-hits
#define SENDWOL_SOCKET_ERROR 1
#define SENDWOL_SEND_ERROR 2
#define LOGFILE_OPEN_ERROR 1 // something wrong with opening the logfile
#define LOGFILE_WRITE_ERROR 2 // could not write to logfile
#define LOGFILE_TEMP_ERROR 3 // could not open to tempfile
#define SMS_SENDER_VALID 0 // The # for the cell-phone we want to send SMS to is valid
#define SMS_SENDER_NOTVALID 1 // The # for the cell-phone we want to send SMS to is invalid
#define MESSAGE_CREATE_OK 0 // the textfile could be created
#define MESSAGE_CREATE_FAIL 1 // the textfile could not be created
#define CELL_PHONE_FOUND 0 // we found a valid cell-phone-# in config-file
#define CELL_PHONE_NOT_FOUND 1 // we did not find a valid cell-phone-# in config-file
#define MAIL_ADDRESS_FOUND 0 // we found a valid mailaddress in config-file
#define MAIL_ADDRESS_NOT_FOUND 1 // we did not find a mailaddress in config-file
#define MAIL_SENDER_VALID 0 // The mailaddress we received a mail is valid
#define MAIL_SENDER_NOTVALID 1 // The mailaddress we received a mail is valid
#define PING_HOST_ONLINE 0 // ping returns host is online
#define PING_UNKNOWN_HOST 1 // ping returns that host is unknown
#define PING_HOST_OFFLINE 2 // the host is known but offline
#define PING_PIPE_ERROR 3 // something wrong with the pipe
const char version_of_program[] = "message2action version 0.27\n";
// filename where config-values for message2action is read from:
//const char config_filename[] = "/home/pi/message2action/message2action.ini";
const char config_filename[] = "message2action.ini";
// command in message which tells Raspberry to reboot:
char reboot_pi_command[80];
const char reboot_pi_command_string[] = "reboot_pi_command"; // this is the string in ini-file we are searching for in order to find a specific command
// command in message which tells Raspberry to shutdown:
char shutdown_pi_command[80];
const char shutdown_pi_command_string[] = "shutdown_pi_command";
// command in message which tells message2action to stop processing:
char message2action_stop_command[40];
const char message2action_stop_command_string[] = "message2action_stop_command";
// filename where the stop-command will be written to done by message2action itself to stop processing:
char message2action_stop_filename[20];
const char message2action_stop_filename_string[] = "message2action_stop_filename";
// command which causes the program to send back the current status of the program and the Pi:
char status_pi_command[80];
const char status_pi_command_string[] = "status_pi_command";
// path where message2action reads incoming SMS-text-messages:
char path_incoming_SMS[100] = "\0"; // default is empty
const char path_incoming_SMS_string[] = "path_incoming_SMS";
// path where message2action reads incoming mails:
char path_incoming_mail[100] = "\0"; // default is empty
const char path_incoming_mail_string[] = "path_incoming_mail";
// path where message2action reads incoming pushbullet-messages:
char path_incoming_pushbullet[100] = "\0"; // default is empty
const char path_incoming_pushbullet_string[] = "path_incoming_pushbullet";
// path where message2action writes outgoing SMS-text-messages:
char path_outgoing_SMS[100] = "\0"; // default is empty
const char path_outgoing_SMS_string[] = "path_outgoing_SMS";
// path where message2action writes outgoing pushbullet-messages:
char path_outgoing_pushbullet[100] = "\0"; // default is empty
const char path_outgoing_pushbullet_string[] = "path_outgoing_pushbullet";
// path where the read and processed SMS-text-messages will be moved after reading and processing
char path_processed_SMS[100] = "\0"; // default is empty
const char path_processed_SMS_string[] = "path_processed_SMS";
// path where the read and processed mails will be moved after reading and processing
char path_processed_mail[100] = "\0"; // default is empty
const char path_processed_mail_string[] = "path_processed_mail";
// path where the read and processed pushbullet-messages will be moved after reading and processing
char path_processed_pushbullet[100] = "\0"; // default is empty
const char path_processed_pushbullet_string[] = "path_processed_pushbullet";
// the file were the content of the mail will be saved which is send with ssmtp:
char fullpath_outgoing_mail[100] = "\0"; // default is empty
const char fullpath_outgoing_mail_string[] = "fullpath_outgoing_mail";
// the file with the shell-skript which is called by systemd-timer to send the mail out:
char fullpath_systemd_shell_mail[100] = "\0"; // default is empty
const char fullpath_systemd_shell_mail_string[] = "fullpath_systemd_shell_mail";
// the path to program ssmtp which is called to send mails out by systemd:
char fullpath_ssmtp[100] ="/usr/sbin/ssmtp";
const char fullpath_ssmtp_string[] = "fullpath_ssmtp";
// path where process-id of the current programm is written to:
char fullpath_smsfile_PID[100] = "\0"; // default is empty
const char fullpath_file_PID_string[] = "fullpath_smsfile_PID";
char fullpath_mailfile_PID[100] = "\0"; // default is empty
const char fullpath_mailfile_PID_string[] = "fullpath_mailfile_PID";
char fullpath_pushbulletfile_PID[100] = "\0"; // default is empty
const char fullpath_pushbulletfile_PID_string[] = "fullpath_pushbulletfile_PID";
//path where logfile of message2action is saved:
char file_logfile[100];
const char file_logfile_string[] = "file_logfile";
// max size of the logfile expressed in kBytes:
char max_size_logfile[12] = "500";
const char max_size_logfile_string[] = "max_size_logfile";
long max_size_logfile_long = 500; // if ini-file could not be read correctly we take 500 as default
// time for waiting for next SMS specified in seconds:
char wait_time_next_sms[6]; // greatest value is 99999 seconds
char wait_time_next_sms_string[] = "wait_time_next_sms";
unsigned long wait_time_next_sms_long;
// time for waiting for next mail specified in seconds:
char wait_time_next_mail[6]; // greatest value is 99999 seconds
char wait_time_next_mail_string[] = "wait_time_next_mail";
unsigned long wait_time_next_mail_long;
// time for waiting for next pushbullet specified in seconds:
char wait_time_next_pushbullet[6]; // greatest value is 99999 seconds
char wait_time_next_pushbullet_string[] = "wait_time_next_pushbullet";
unsigned long wait_time_next_pushbullet_long;
// suffix following WOL00 ... WOL09 in order to check for online status:
char online_status_command_suffix[20] = "";
const char online_status_command_sufffix_string[] = "online_status_command_suffix";
// wait time in seconds after sending out WOL to a device: after this wait time the devices will be checked if it online:
char check_online_status_waittime[3] = "30"; // default is 30 seconds
const char check_online_status_waittime_string[] = "check_online_status_waittime";
unsigned long check_online_status_waittime_long = 30; // default is 30 seconds
// 10 cell-phone-# from which we can send SMS to our Pi:
char cell_phone_00[20] = "\0";
char cell_phone_01[20] = "\0";
char cell_phone_02[20] = "\0";
char cell_phone_03[20] = "\0";
char cell_phone_04[20] = "\0";
char cell_phone_05[20] = "\0";
char cell_phone_06[20] = "\0";
char cell_phone_07[20] = "\0";
char cell_phone_08[20] = "\0";
char cell_phone_09[20] = "\0";
// 10 emailadresses which we can send mails to our Pi:
char mail_address_00[40] = "\0";
char mail_address_01[40] = "\0";
char mail_address_02[40] = "\0";
char mail_address_03[40] = "\0";
char mail_address_04[40] = "\0";
char mail_address_05[40] = "\0";
char mail_address_06[40] = "\0";
char mail_address_07[40] = "\0";
char mail_address_08[40] = "\0";
char mail_address_09[40] = "\0";
// 10 commands which can be send to raspberry
char messsagecommand_00[80] = "\0";
char messsagecommand_01[80] = "\0";
char messsagecommand_02[80] = "\0";
char messsagecommand_03[80] = "\0";
char messsagecommand_04[80] = "\0";
char messsagecommand_05[80] = "\0";
char messsagecommand_06[80] = "\0";
char messsagecommand_07[80] = "\0";
char messsagecommand_08[80] = "\0";
char messsagecommand_09[80] = "\0";
char default_MAC_address[] = "00:00:00:00:00:00";
// 10 MAC-adresses for sending WOL-broadcast to: 6 times 2 charackters + 6 times a ':' + '\0' :
char WOL_MAC_00[100] = "00:00:00:00:00:00";
char WOL_MAC_01[100] = "00:00:00:00:00:00";
char WOL_MAC_02[100] = "00:00:00:00:00:00";
char WOL_MAC_03[100] = "00:00:00:00:00:00";
char WOL_MAC_04[100] = "00:00:00:00:00:00";
char WOL_MAC_05[100] = "00:00:00:00:00:00";
char WOL_MAC_06[100] = "00:00:00:00:00:00";
char WOL_MAC_07[100] = "00:00:00:00:00:00";
char WOL_MAC_08[100] = "00:00:00:00:00:00";
char WOL_MAC_09[100] = "00:00:00:00:00:00";
// 10 MAC-adresses in hex-format without any delimeters, 6 times 1 chars
char WOL_MAC_00_hex[6];
char WOL_MAC_01_hex[6];
char WOL_MAC_02_hex[6];
char WOL_MAC_03_hex[6];
char WOL_MAC_04_hex[6];
char WOL_MAC_05_hex[6];
char WOL_MAC_06_hex[6];
char WOL_MAC_07_hex[6];
char WOL_MAC_08_hex[6];
char WOL_MAC_09_hex[6];
// 10 IP-adresses in V4-format. 3 times 3 digits + '.' + 3 digits + \0
char ip_address_00[16] = "\0";
char ip_address_01[16] = "\0";
char ip_address_02[16] = "\0";
char ip_address_03[16] = "\0";
char ip_address_04[16] = "\0";
char ip_address_05[16] = "\0";
char ip_address_06[16] = "\0";
char ip_address_07[16] = "\0";
char ip_address_08[16] = "\0";
char ip_address_09[16] = "\0";
// 10 hostnames, each not longer than 75 chars:
char hostname_00[75] = "\0";
char hostname_01[75] = "\0";
char hostname_02[75] = "\0";
char hostname_03[75] = "\0";
char hostname_04[75] = "\0";
char hostname_05[75] = "\0";
char hostname_06[75] = "\0";
char hostname_07[75] = "\0";
char hostname_08[75] = "\0";
char hostname_09[75] = "\0";
// array of pointers to chars for storing all strings to search in configfile:
const char *configparameters[] = { "reboot_pi_command", "shutdown_pi_command", "status_pi_command",
"message2action_stop_command", "message2action_stop_filename",
"path_incoming_SMS", "path_outgoing_SMS", "path_processed_SMS", "wait_time_next_sms",
"path_incoming_mail", "fullpath_outgoing_mail", "path_processed_mail", "wait_time_next_mail", "fullpath_systemd_shell_mail", "fullpath_ssmtp",
"path_incoming_pushbullet", "path_outgoing_pushbullet", "path_processed_pushbullet", "wait_time_next_pushbullet",
"file_logfile", "max_size_logfile", "fullpath_smsfile_PID", "fullpath_mailfile_PID","fullpath_pushbulletfile_PID", "online_status_command_suffix", "check_online_status_waittime",
"cell_phone00", "cell_phone01", "cell_phone02", "cell_phone03", "cell_phone04", "cell_phone05", "cell_phone06", "cell_phone07", "cell_phone08", "cell_phone09",
"mail_address_00", "mail_address_01", "mail_address_02", "mail_address_03", "mail_address_04", "mail_address_05", "mail_address_06", "mail_address_07", "mail_address_08", "mail_address_09",
"CMD00", "CMD01", "CMD02", "CMD03", "CMD04", "CMD05", "CMD06", "CMD07", "CMD08", "CMD09",
"WOL00", "WOL01", "WOL02", "WOL03", "WOL04", "WOL05", "WOL06", "WOL07", "WOL08", "WOL09",
'\0'}; // NULL-pointer marks end of array, do not delete this entry
// array of pointers for storing the values we have in ini-file:
char *configvariables[] = { reboot_pi_command, shutdown_pi_command, status_pi_command,
message2action_stop_command, message2action_stop_filename,
path_incoming_SMS, path_outgoing_SMS, path_processed_SMS, wait_time_next_sms,
path_incoming_mail, fullpath_outgoing_mail, path_processed_mail, wait_time_next_mail, fullpath_systemd_shell_mail, fullpath_ssmtp,
path_incoming_pushbullet, path_outgoing_pushbullet, path_processed_pushbullet, wait_time_next_pushbullet,
file_logfile, max_size_logfile, fullpath_smsfile_PID, fullpath_mailfile_PID, fullpath_pushbulletfile_PID, online_status_command_suffix, check_online_status_waittime,
cell_phone_00, cell_phone_01, cell_phone_02, cell_phone_03, cell_phone_04, cell_phone_05, cell_phone_06, cell_phone_07, cell_phone_08, cell_phone_09,
mail_address_00, mail_address_01, mail_address_02, mail_address_03, mail_address_04, mail_address_05, mail_address_06, mail_address_07, mail_address_08, mail_address_09,
messsagecommand_00, messsagecommand_01, messsagecommand_02, messsagecommand_03, messsagecommand_04, messsagecommand_05, messsagecommand_06, messsagecommand_07, messsagecommand_08, messsagecommand_09,
WOL_MAC_00, WOL_MAC_01, WOL_MAC_02, WOL_MAC_03, WOL_MAC_04, WOL_MAC_05, WOL_MAC_06, WOL_MAC_07, WOL_MAC_08, WOL_MAC_09,
ip_address_00, ip_address_01, ip_address_02, ip_address_03, ip_address_04, ip_address_05, ip_address_06, ip_address_07, ip_address_08, ip_address_09,
hostname_00, hostname_01, hostname_02, hostname_03, hostname_04, hostname_05, hostname_06, hostname_07, hostname_08, hostname_09,
'\0'}; // NULL-pointer marks end of array, do not delete this entry
// enumeration of the variables we have in config-file:
enum configcount { reboot_pi_command_count, shutdown_pi_command_count, status_pi_command_count,
message2action_stop_command_count, message2action_stop_filename_count,
path_incoming_SMS_count, path_outgoing_SMS_count, path_processed_SMS_count, wait_time_next_sms_count,
path_incoming_mail_count, fullpath_outgoing_mail_count, path_processed_mail_count, wait_time_next_mail_count, fullpath_systemd_shell_mail_count, fullpath_ssmtp_count,
path_incoming_pushbullet_count, path_outgoing_pushbullet_count, path_processed_pushbullet_count, wait_time_next_pushbullet_count,
file_logfile_count, max_lines_logfile_count, smsfile_PID_count, mailfile_PID_count, pushbulletfile_PID_count, online_status_command_suffix_count, check_online_status_waittime_count,
cell_phone00_count, cell_phone01_count, cell_phone02_count, cell_phone03_count, cell_phone04_count, cell_phone05_count, cell_phone06_count, cell_phone07_count, cell_phone08_count, cell_phone09_count,
mail_address_00_count, mail_address_01_count, mail_address_02_count, mail_address_03_count, mail_address_04_count, mail_address_05_count, mail_address_06_count, mail_address_07_count, mail_address_08_count, mail_address_09_count,
messsagecommand_00_count, messsagecommand_01_count, messsagecommand_02_count, messsagecommand_03_count, messsagecommand_04_count, messsagecommand_05_count, messsagecommand_06_count, messsagecommand_07_count, messsagecommand_08_count, messsagecommand_09_count,
WOL_MAC_00_count, WOL_MAC_01_count, WOL_MAC_02_count, WOL_MAC_03_count, WOL_MAC_04_count, WOL_MAC_05_count, WOL_MAC_06_count, WOL_MAC_07_count, WOL_MAC_08_count, WOL_MAC_09_count,
ip_address_00_count, ip_address_01_count, ip_address_02_count, ip_address_03_count, ip_address_04_count, ip_address_05_count, ip_address_06_count, ip_address_07_count, ip_address_08_count, ip_address_09_count,
hostname_00_count, hostname_01_count, hostname_02_count, hostname_03_count, hostname_04_count, hostname_05_count, hostname_06_count, hostname_07_count, hostname_08_count, hostname_09_count
};
int configparametercount = 0; // # of configparameters we have to search for
const char *cmdline_parameters[] = { // list of commandlineparameter which can be used
"config", "?", "stopsignal", "stopfile", "ini=",
"display=y", "display=n", "log=y", "log=n",
"out=sms", "out=mail", "out=pushbullet",
"in=sms", "in=mail", "in=pushbullet",
'\0' // marks end of array
};
enum cmdline_parameter_count {
config_counter, questionmark_counter, stopsignal_counter, stopfile_counter, inifile_counter,
display_yes_counter, display_no_counter, log_yes_counter, log_no_counter,
outbound_sms_counter, outbound_mail_counter, outbound_pushbullet_counter, // we count first for outgoing parameters because we search for them first
inbound_sms_counter, inbound_mail_counter, inbound_pushbullet_counter,
};
int reboot_piflag = FALSE; // flags if we have to reboot the Raspberry Pi, default is no
int shutdown_piflag = FALSE; // flags if we have to shutdown the Raspberry Pi, default is no
// global variables because we can have warnings and erros is any function. The variables are only changed in function write_logfile
unsigned int warningcounter = 0; // counts the # of warnings we had
unsigned int errorcounter = 0; // counts the # of errors we had
// global variable:
volatile sig_atomic_t processingflag = TRUE; // if TRUE: yes, we are still processing, =FALSE, no, we stop processing
// flags can have only value = 0 (not set) or 1 (set)
// the following flags sign if we have found a specific commandlline-parameter. For example: if cmdline_logflag is TRUE than we know that we have to log in loggingfile
int cmdline_startflag = 0;
int cmdline_logflag = 0;
int cmdline_stopflag = 0;
int cmdline_helpflag = 0;
int cmdline_displayflag = 0;
int cmdline_configflag = 0;
int cmdline_signalflag = 0;
int cmdline_flag = 0;
int logging_flag = 0;
int display_flag = 0;
int inbound_flag = 0; // flags if we have defined the inputchannel like sms, mail
int inbound_sms_flag = 0;
int inbound_mail_flag = 0;
int inbound_pushbullet_flag = 0;
int outbound_sms_flag = 0;
int outbound_mail_flag = 0;
int outbound_pushbullet_flag = 0;
int valid_parameter_found_flag = 0;
int stopsignal_flag = 0;
int stopfile_flag = 0;
#define LOGGING_FALSE 0 // logging is disabled
#define LOGGING_TRUE 1 // logging is enabled
#define DISPLAY_FALSE 0 // displaying is disabled, this is quiete mode
#define DISPLAY_TRUE 1 // displaying is enabled
#define LOG_ERROR 0 // do we have an error to log or do we have an information to log
#define LOG_INFO 1 // we log an information only
#define LOG_WARNING 2 // we log a warning
#define STOPSIGNAL_TRUE 1 // we have to stop program by sending a signal
#define STOPFILE_TRUE 1 // we have to stop program by creating a file which contains stop-message
//*****************************************************************************************************************
// upcase_string : each char in string will be in upper case ('a' to 'A', 'g' to 'G')
// input: string to modify and to write result to
// returncodes: 0 = no error
// !=0 = any error
//*****************************************************************************************************************
void upcase_string(char* input) {
// char tempstring[MAX_CHARS_PER_LINE_CONFIGFILE] = "";
unsigned int tempint;
unsigned int stringlength;
// strncpy(tempstring, input, MAX_CHARS_PER_LINE_CONFIGFILE - 1); // we save input in temp
stringlength = strlen(input);
for (tempint = 0; tempint < stringlength; tempint++) {
input[tempint] = toupper(input[tempint]);
}
} // end of upcase_string ***************************************************************************************
//*****************************************************************************************************************
// write_logfile: writes content to logfile. Date + time is in the beginning of each line. If the logfile becomes too
// large, the file will be divided by 2.
// input: string to write to logfile
// returncodes: 0 = no error
// 1 = any error
//*****************************************************************************************************************
int write_logfile(const char* logcontent, const int message_flag) {
time_t timestamp_time;
struct tm *timestamp_tm;
char date_time[20] = "01.01.2000 01:01:01"; // string to save date + time, this is default-value
FILE *logfile;
FILE *tempfile;
unsigned linecounter;
unsigned counter;
char logfileline[MAX_CHARS_PER_LINE_LOGFILE];
struct stat fileattributes;
char tempfilename[100 + 4] = "";
if (message_flag == LOG_WARNING) warningcounter++; // if we have a warning we have to increment the counter
if (message_flag == LOG_ERROR) errorcounter++; // if we have an error we have to increment the counter
if ((logging_flag == LOGGING_TRUE) || ((message_flag == LOG_ERROR) || (message_flag == LOG_WARNING))) { // we log only when logging is enabled or if we have an error
time(×tamp_time);
timestamp_tm = localtime( ×tamp_time);
strftime(date_time, 20, "%d.%m.%Y %H:%M:%S", timestamp_tm);
logfile = fopen(file_logfile, "a+");
if (logfile != 0) { // logfile could be opened
fprintf(logfile, "%s : %s", date_time, logcontent); //we add to the logfile one new line
// now we check if we have reached the maximum # of lines in the logfile
stat(file_logfile, &fileattributes);
if (fileattributes.st_size > max_size_logfile_long*1024) { // file is to big, we have to divide it by 2:
fprintf(logfile, "%s : %s\n", date_time, "Info: Logfile was truncated due to limit of size."); //we add to the logfile one new line
rewind(logfile);
for (linecounter = 0; fgets(logfileline, MAX_CHARS_PER_LINE_LOGFILE, logfile) != 0; linecounter++) ;
rewind(logfile);
linecounter = linecounter / 2;
for (counter = 0; counter < linecounter; counter++) fgets(logfileline, MAX_CHARS_PER_LINE_LOGFILE, logfile); // we step to the position from which we want to read from
strcpy(tempfilename, file_logfile);
strcat(tempfilename, ".tmp");
tempfile = fopen(tempfilename, "w+");
if (tempfile != 0) { // now we copy from logfile to tempfile the newest lines:
while ( fgets(logfileline, MAX_CHARS_PER_LINE_LOGFILE, logfile) != 0) {
fputs(logfileline, tempfile);
}
fclose(tempfile);
remove(file_logfile);
rename(tempfilename, file_logfile);
if (message_flag == LOG_ERROR) errorcounter++; // we increment counter for errors
if (message_flag == LOG_WARNING) warningcounter++; // we increment counter for warnings
} else { // tempfile could not be opened
printf("Error: Temporary file for truncating logfile could not be opened!\n");
return LOGFILE_TEMP_ERROR;
}
} // end of if logfile is too big
fclose(logfile);
} else {
printf("Error: Logfile %s could not be opened! Message: %s\n", file_logfile, logcontent);
return LOGFILE_OPEN_ERROR;
}
}
if ((display_flag == DISPLAY_TRUE) || (message_flag == LOG_ERROR))
printf("\r%s", logcontent) ; // we print error-message on the screen in any cases but we print info-message only when global display-flag is true
return 0;
} // end of write_logfile ***************************************************************
//*****************************************************************************************************************
// gethexvaluefromstring: converts a string to its hex-value. For example string "A9" will be converted to 0xa9.
// input: buffer : the source where to read from, it is a string, for example "A9"
// hexvalue: the value in hex-form, for example 0xa9
// returncodes: 0 = no error
// 1, 2 = any error
//*****************************************************************************************************************
unsigned gethexvaluefromstring(char *buffer, char *hexvalue) {
unsigned temp = 0;
// printf("Eingabewert #1: %c\n", buffer[0]);
switch (buffer[0]) {
case '0': *hexvalue = 0; break;
case '1': *hexvalue = 16; break;
case '2': *hexvalue = 32; break;
case '3': *hexvalue = 48; break;
case '4': *hexvalue = 64; break;
case '5': *hexvalue = 80; break;
case '6': *hexvalue = 96; break;
case '7': *hexvalue = 112; break;
case '8': *hexvalue = 128; break;
case '9': *hexvalue = 144; break;
case 'A': *hexvalue = 160; break;
case 'B': *hexvalue = 176; break;
case 'C': *hexvalue = 192; break;
case 'D': *hexvalue = 208; break;
case 'E': *hexvalue = 224; break;
case 'F': *hexvalue = 240; break;
default: temp = 1; break; // we don't have a valid charackter, the value != 0 is our flag for this
}
// printf("Eingabewert #2: %c\n", buffer[1]);
switch (buffer[1]) {
case '0': *hexvalue += 0; break;
case '1': *hexvalue += 1; break;
case '2': *hexvalue += 2; break;
case '3': *hexvalue += 3; break;
case '4': *hexvalue += 4; break;
case '5': *hexvalue += 5; break;
case '6': *hexvalue += 6; break;
case '7': *hexvalue += 7; break;
case '8': *hexvalue += 8; break;
case '9': *hexvalue += 9; break;
case 'A': *hexvalue += 10; break;
case 'B': *hexvalue += 11; break;
case 'C': *hexvalue += 12; break;
case 'D': *hexvalue += 13; break;
case 'E': *hexvalue += 14; break;
case 'F': *hexvalue += 15; break;
default: temp = 2; break; // we don't have a valid charackter, the value != 0 is our flag for this
}
// printf("temphex: %i\n", temphex);
return (temp);
}
//*****************************************************************************************************************
// read_config_file: reads content of message2action.ini and fills global variables from ini-file
// input: name of config-file for message2action
// returncodes: 0 = no error
// != 0 = any error
//*****************************************************************************************************************
unsigned int read_config_file(const char* configfilename) {
DIR *tempdirectory; // the directory which will be checked for plausibility only
FILE *configfilep; // file-handler which contains the config-file
FILE *logfile; // file-handler which contains the logfile
FILE *tempfile;
char configfileline[MAX_CHARS_PER_LINE_CONFIGFILE];
struct stat fileattributes;
long filepos = 0;
int tempint = 0;
int length = 0;
int counter = 0;
unsigned int valid_cellphonenumber_flag = FALSE; // flags if we have found minimum 1 valid cell-phone in ini-file
char digitstring[20] = "";
char *fileposcommentmarker; // position of '#'
char *fileposNL; // position of '\n'
// char *fileposblank; // position of blank behind the value in the line of the ini-file
char *fileposequalsign; // position of '=' in ini-file
char *configparameterpos; // position of variable in ini file. The variable can also be written with leading blanks in front
int valuelength = 0; // number of charackters the value has in ini-file
char *stop_ptr = 0;
char logentry[150]; // one line for the logfile
configfilep = fopen(configfilename, "r");
if (configfilep != 0) { // opening of configfile was successfull
stat(config_filename, &fileattributes);
if (fileattributes.st_size > MAX_CONFIG_FILE_SIZE)
{ // filesize of config-file is greater than specified, we stop here
printf("Error: Filesize of configfile is too large: %ld bytes.\n", fileattributes.st_size);
fclose(configfilep); // close file, it can not be processed
return CONFIGFILESIZEERROR;
} else { // file is small enough, we start to extract all config-parameters:
memset(configfileline, '\0', MAX_CHARS_PER_LINE_CONFIGFILE);
while (configparameters[configparametercount++] != '\0'); // look for NULL-pointer at end of array in order to determine the # of parameters we have to search for.
configparametercount--; // configparametercount will be set with the number of configparameters we have: '\0' does not belong to the commands
while ( fgets(configfileline, MAX_CHARS_PER_LINE_CONFIGFILE, configfilep) != 0) {
fileposequalsign = strchr(configfileline, '=');
fileposcommentmarker = strchr(configfileline, '#');
fileposNL = strchr(configfileline, '\n');
if (fileposcommentmarker != 0) { // if '#' is in the line then delete all signs between '#' and '\n' but leave '\n' in line
memset(fileposcommentmarker, ' ', fileposNL - fileposcommentmarker);
}
for (tempint = 0; tempint < configparametercount ; tempint++ ) {
configparameterpos = strstr(configfileline, configparameters[tempint]);
if ( configparameterpos != 0) { // if we find in current line the name of the variable, we copy the value as written in ini-file to our variable
valuelength = fileposNL - fileposequalsign - 1;
strncpy( configvariables[tempint], configparameterpos + strlen(configparameters[tempint]) + 1, valuelength );
memset(configvariables[tempint] + valuelength, '\0', 1); // terminate string with a NULL
if ( ((tempint >= reboot_pi_command_count) && (tempint <= message2action_stop_command_count)) || ((tempint >= mail_address_00_count) && (tempint <=mail_address_09_count )) || tempint == online_status_command_suffix_count)
// we upcase only the first variables and the mailaddresses and the MAC-addresses. The other variables must not be modified because they are case sensitive
upcase_string(configvariables[tempint]);
}
} // end of for-loop
filepos += strlen(configfileline); // calculate how many chars we have to seek in file for next line in file
fseek(configfilep, filepos, SEEK_SET);
memset(configfileline, '\0', MAX_CHARS_PER_LINE_CONFIGFILE);
} // end of while-loop
fclose(configfilep); // close file, we have all parameters from ini-file
// now we do some plausibility-checks concerning the parameters we have read from ini-file:
// first we check if we have a valid value for the logfile:
logfile = fopen(file_logfile, "a+");
if (logfile != NULL) { // value for logfile is correct
fclose(logfile);
} else { // value for logfile is not correct
printf("Error: logfile can not be opened for writing: %s!\n", file_logfile);
return(CONFIG_FILE_PATH_LOGFILE_ERROR);
}
// we check the MAC-adresses in ini-file:
for (tempint = 0; tempint < 6; tempint++) {
if (gethexvaluefromstring(&WOL_MAC_00[3*tempint], &WOL_MAC_00_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL00 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
if (gethexvaluefromstring(&WOL_MAC_01[3*tempint], &WOL_MAC_01_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL01 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
if (gethexvaluefromstring(&WOL_MAC_02[3*tempint], &WOL_MAC_02_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL02 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
if (gethexvaluefromstring(&WOL_MAC_03[3*tempint], &WOL_MAC_03_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL03 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
if (gethexvaluefromstring(&WOL_MAC_04[3*tempint], &WOL_MAC_04_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL04 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
if (gethexvaluefromstring(&WOL_MAC_05[3*tempint], &WOL_MAC_05_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL05 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
if (gethexvaluefromstring(&WOL_MAC_06[3*tempint], &WOL_MAC_06_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL06 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
if (gethexvaluefromstring(&WOL_MAC_07[3*tempint], &WOL_MAC_07_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL07 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
if (gethexvaluefromstring(&WOL_MAC_08[3*tempint], &WOL_MAC_08_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL08 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
if (gethexvaluefromstring(&WOL_MAC_09[3*tempint], &WOL_MAC_09_hex[tempint]) != 0) { write_logfile("Error: MAC-address WOL09 in ini-file is not valid!\n", LOG_ERROR); return CONFIG_FILE_MAC_ERROR;}
} // end of for-loop
// we check now if we have an ip-address or a hostname behind the MAC-address:
for (tempint = WOL_MAC_00_count; tempint < WOL_MAC_09_count; tempint++) {
if (strcmp(configvariables[tempint], default_MAC_address) != 0) {
configparameterpos = strstr(configvariables[tempint], "host=");
// printf("Inhalt: %s\n", configvariables[tempint]);
if ( configparameterpos != 0 ) { // we have a host-name behind MAC-address:
fileposequalsign = strchr(configvariables[tempint], '=');
valuelength = strlen(configvariables[tempint]) - 23;
strncpy(configvariables[tempint + hostname_00_count - WOL_MAC_00_count], configparameterpos + 5, valuelength);
memset(configvariables[tempint] + 17, 0, 1); // we terminate MAC-address with \0
} else { // check if we have an ip-address behind MAC-address:
configparameterpos = strstr(configvariables[tempint], "ip=");
if (configparameterpos != 0 ) {
fileposequalsign = strchr(configvariables[tempint], '=');
valuelength = strlen(configvariables[tempint]) - 21;
strncpy(configvariables[tempint + ip_address_00_count - WOL_MAC_00_count], configparameterpos + 3, valuelength);
memset(configvariables[tempint] + 17, 0, 1); // we terminate MAC-address with \0
}
}
// now we check if we had either host or ip specified:
if (configparameterpos == NULL) {
sprintf(logentry, "Error: Neither ip-address nor hostname related to MAC-addresss #%d: %s!\n", tempint - WOL_MAC_00_count, configvariables[tempint]);
write_logfile(logentry, LOG_ERROR);
return(CONFIG_FILE_IP_OR_HOST_MISSING_ERROR);
}
} // end of if (strcmp(configvariables[tempint], default_MAC_address) != 0)
} // end of for-loop (tempint = WOL_MAC_00_count; tempint < WOL_MAC_09_count; tempint++)
// we check receiving and sending cell-phone-#:
// Note: on 32-bit-OS unsigned long can have maximum 10 digits but cellphone-# can have more than 10 digits. So we have to convert each digit separatly:
for (tempint = 0; tempint < 10; tempint++) {
length = strlen(configvariables[cell_phone00_count + tempint]);
if (length > 0) valid_cellphonenumber_flag = TRUE;
strcpy(digitstring, configvariables[cell_phone00_count + tempint]);
for (counter = 0; counter < length; counter++) {
if ( !(digitstring[counter] >= '0' && digitstring[counter] <= '9')) {
printf("Error: Invalid sign \"%c\" in cell-phone number #%d in ini-file!\n", digitstring[counter], tempint + 1);
return CONFIG_FILE_CELL_PHONE_STRING_ERROR;
}
} // end of for-loop
} // end of for-loop
if (valid_cellphonenumber_flag == FALSE) {
printf("Error: no valid cell-phone-number found in ini-file!\n");
return CONFIG_FILE_CELL_PHONE_FOUND_ERROR;
}
// we convert the filesize of logfile to integer:
max_size_logfile_long = strtoul(max_size_logfile, &stop_ptr, 10);
if (*stop_ptr != 0) {
printf("Error: %s is not valid for parameter \"max_size_logfile\" in inifile!\n", max_size_logfile );
return CONFIG_FILE_MAX_LOGFILE_ERROR;
}
// we have to convert the value for the wait-time for next SMS:
wait_time_next_sms_long = strtoul(wait_time_next_sms, &stop_ptr,10);
if (*stop_ptr != 0) {
printf("Error: Invalid value for parameter %s in inifile: %s!\n", wait_time_next_sms_string, wait_time_next_sms);
return CONFIG_FILE_WAIT_TIME_NEXT_MESSAGE_ERROR;
}
// we have to convert the value for the wait-time for next mail:
wait_time_next_mail_long = strtoul(wait_time_next_mail, &stop_ptr,10);
if (*stop_ptr != 0) {
printf("Error: Invalid value for parameter %s in inifile: %s!\n", wait_time_next_mail_string, wait_time_next_mail);
return CONFIG_FILE_WAIT_TIME_NEXT_MESSAGE_ERROR;
}
// we check the path for incoming SMS:
if (strlen(path_incoming_SMS) > 0) { // there's a value given in ini-file
tempdirectory = opendir(path_incoming_SMS);
if (tempdirectory != 0) closedir(tempdirectory);
else {
sprintf(logentry, "Error: path for incoming SMS is not valid: %s!\n", path_incoming_SMS);
write_logfile(logentry, LOG_ERROR);
return(CONFIG_FILE_PATH_INCOMING_SMS_ERROR);
}
} else { // we have no value in ini-file:
write_logfile("Warning: path for incoming SMS is not specified in ini-file!\n", LOG_WARNING);
}
// we check the path for outgoing SMS:
if (strlen(path_outgoing_SMS) > 0) { // there's a value given in ini-file
tempdirectory = opendir(path_outgoing_SMS);
if (tempdirectory != 0) closedir(tempdirectory);
else { // directory does not exist:
sprintf(logentry, "Error: path for incoming SMS is not valid: %s!\n", path_outgoing_SMS);
write_logfile(logentry, LOG_ERROR);
return(CONFIG_FILE_PATH_OUTGOING_SMS_ERROR);
}
} else { // we have no value in ini-file:
write_logfile("Warning: path for outgoing SMS is not specified in ini-file!\n", LOG_WARNING);
}
// we check the path for processed SMS:
if (strlen(path_processed_SMS) > 0) { // there's a value given in ini-file
tempdirectory = opendir(path_processed_SMS);
if (tempdirectory != 0) closedir(tempdirectory);
else { // directory does not exist:
sprintf(logentry, "Error: path for processed SMS is not valid: %s!\n", path_processed_SMS);
write_logfile(logentry, LOG_ERROR);
return(CONFIG_FILE_PATH_PROCESSED_SMS_ERROR);
}
} else { // we have no value in ini-file:
write_logfile("Warning: path for processed SMS is not specified in ini-file!\n", LOG_WARNING);
}
// we check file for saving process-ID for SMS:
if (strlen(fullpath_file_PID_string) == 0) // we have no value in ini-file:
write_logfile("Warning: file for saving PID for SMS is not specified in ini-file!\n", LOG_WARNING);
// we check the path for incoming mail:
if (strlen(path_incoming_mail) > 0) { // there's a value given in ini-file
tempdirectory = opendir(path_incoming_mail);
if (tempdirectory != 0) closedir(tempdirectory);
else {
sprintf(logentry, "Error: path for incoming mail is not valid: %s!\n", path_incoming_mail);
write_logfile(logentry, LOG_ERROR);
return(CONFIG_FILE_PATH_INCOMING_MAIL_ERROR);
}
} else { // we have no value in ini-file:
write_logfile("Warning: path for incoming mail is not specified in ini-file!\n", LOG_WARNING);
}
// we check the path for outgoing mail:
if (strlen(fullpath_outgoing_mail) > 0) { // there's a value given in ini-file
tempfile = fopen(fullpath_outgoing_mail, "w+");
if (tempfile != 0) {
fclose(tempfile);
remove(fullpath_outgoing_mail); // we delete the empty file again
} else { // directory does not exist:
sprintf(logentry, "Error: filename for outgoing mail is not valid: %s!\n", fullpath_outgoing_mail);
write_logfile(logentry, LOG_ERROR);
return(CONFIG_FILE_PATH_OUTGOING_MAIL_ERROR);
}
} else { // we have no value in ini-file:
write_logfile("Warning: path for outgoing mail is not specified in ini-file!\n", LOG_WARNING);
}
// we check the path for processed mail:
if (strlen(path_processed_mail) > 0) { // there's a value given in ini-file
tempdirectory = opendir(path_processed_mail);
if (tempdirectory != 0) closedir(tempdirectory);
else { // directory does not exist:
sprintf(logentry, "Error: path for processed mail is not valid: %s!\n", path_processed_mail);
write_logfile(logentry, LOG_ERROR);
return(CONFIG_FILE_PATH_PROCESSED_MAIL_ERROR);
}
} else { // we have no value in ini-file:
write_logfile("Warning: path for processed mail is not specified in ini-file!\n", LOG_WARNING);
}
// we check file for saving process-ID for mail:
if (strlen(fullpath_mailfile_PID) == 0) // there's no value given in ini-file :
write_logfile("Warning: file for saving PID for mail is not specified in ini-file!\n", LOG_WARNING);
// now we check if path to program ssmtp is valid:
if (strlen(fullpath_ssmtp) > 0) { // there's a value given in ini-file
tempint = access(fullpath_ssmtp, F_OK);
if (tempint != 0) { // fullpath does not exist:
sprintf(logentry, "Error: fullpath for ssmtp does not exist: %s!\n", fullpath_ssmtp);
write_logfile(logentry, LOG_ERROR);
return(CONFIG_FILE_FULLPATH_SSMTP_ERROR);
}
} else { // we have no value in ini-file:
write_logfile("Warning: path for processed mail is not specified in ini-file!\n", LOG_WARNING);
}
// we check if check_online_status_waittime is a valid value:
check_online_status_waittime_long = strtoul(check_online_status_waittime, &stop_ptr,10);
if (*stop_ptr != 0) {
printf("Error: Invalid value for parameter %s in inifile: %s!\n", check_online_status_waittime_string, check_online_status_waittime);
return CONFIG_FILE_CHECK_ONLINE_WAIT_TIME_ERROR;
}
} // end of file is small enough, we start to extract all config-parameters
} else { // opening of configfile was NOT successfull
printf("Error: file %s could not be opened for reading!\n", configfilename);
return CONFIG_FILE_READ_ERROR;
};
return NOERROR;
} // end of function read_config_file ***************************************************************
//*****************************************************************************************************************
// print_configfile: prints the content of the lofile on the screen
// input: none
// returncodes: 0 = no error
// 1 = any error
//*****************************************************************************************************************
int print_configfile(void) {
int tempint;
if (read_config_file(config_filename) == NOERROR) {
// now we start to print out every content of the ini-file
printf("Number of parameters found: %d\n", configparametercount);
printf("Commands for Raspberry:\n");
printf("Shutdown: %s. Reboot: %s. Status: %s. Stop: %s\n", shutdown_pi_command, reboot_pi_command, status_pi_command, message2action_stop_command);
printf("Files for saving process-ID, sms: %s; mail: %s\n", fullpath_smsfile_PID, fullpath_mailfile_PID);
printf("Filename for saving stop-message: %s\n", message2action_stop_filename);
printf("Path for incoming SMS: %s, outgoing SMS: %s, processed SMS: %s\n", path_incoming_SMS, path_outgoing_SMS, path_processed_SMS);
printf("Path for incoming mail: %s, outgoing mail-file: %s, processed mail: %s\n", path_incoming_mail, fullpath_outgoing_mail, path_processed_mail);
printf("Path for ssmtp: %s\n", fullpath_ssmtp);
printf("Logfile: %s\n", file_logfile);
printf("Maximum size of logfile (kBytes): %s\n", max_size_logfile);
printf("Maximum size of config-file (bytes): %d\n", MAX_CONFIG_FILE_SIZE);
printf("Time to wait for next message in seconds: ");
printf("SMS: %s | Mail: %s\n", wait_time_next_sms, wait_time_next_mail);
printf("Suffix after WOL00 ... WOL09 for checking onlinestatus: %s\n", online_status_command_suffix);
printf("Waittime after sending WOL for online-check: %s\n", check_online_status_waittime);
// now we print the cell-phone-# :
for (tempint = cell_phone00_count; tempint < cell_phone09_count + 1; tempint++) {
if (strcmp(configvariables[tempint], "\0") == 0) printf("Cellphone # %d: not specified in ini-file.\n", tempint - cell_phone00_count);
else printf("Cellphone # %d: %s\n", tempint - cell_phone00_count , configvariables[tempint]);
} // end of for-loop
// now we print the mailaddresses:
for (tempint = mail_address_00_count; tempint < mail_address_09_count + 1; tempint++) {
if (strcmp(configvariables[tempint], "\0") == 0) printf("Mailaddress # %d: not specified in ini-file.\n", tempint - mail_address_00_count);
else printf("Mailaddress # %d: %s\n", tempint - mail_address_00_count , configvariables[tempint]);
} // end of for-loop
// now we print the commands out which can be send to raspberry:
for (tempint = messsagecommand_00_count; tempint < messsagecommand_09_count + 1; tempint++) {
if (strcmp(configvariables[tempint], "\0") == 0) printf("Message-command # %d: not specified in ini-file.\n", tempint - messsagecommand_00_count);
else printf("Message-command # %d: %s\n", tempint - messsagecommand_00_count , configvariables[tempint]);
} // end of for-loop
// now we print the MAC-addresses to which the WOL-broadcast can be send:
for (tempint = WOL_MAC_00_count; tempint < WOL_MAC_09_count + 1; tempint++) {
if (strcmp(configvariables[tempint], "00:00:00:00:00:00") == 0) printf("WOL-MAC-adress # %d: not specified in ini-file.\n", tempint - WOL_MAC_00_count);
else {
printf("WOL-MAC-adress # %d: %s", tempint - WOL_MAC_00_count, configvariables[tempint]);
if ( strlen( configvariables[tempint + hostname_00_count - WOL_MAC_00_count]) != 0) printf(" with hostname: %s\n", configvariables[tempint + hostname_00_count - WOL_MAC_00_count]); else {
if ( strlen(configvariables[tempint + ip_address_00_count - WOL_MAC_00_count]) != 0) printf(" with ip-address: %s\n", configvariables[tempint + ip_address_00_count - WOL_MAC_00_count]); else printf("\n");
}
}
} // end of for-loop
} else { // anything went wrong with reading the ini-file
printf("Error: reading configfile failed: %s\n", config_filename);
}
return 0;
} // end of function print_configfile ***************************************************************
//*****************************************************************************************************************
// sendWOL: sends out the WOL-message to the a MAC-adress. The MAC-adress is taken from the ini-file.
// input: buffer : the source where to read from, it is a string, for example "A9"
// returncodes: 0 = no error
// != 0 means any error
//*****************************************************************************************************************
unsigned sendWOL(char *WOL_hex) {
unsigned int tempint;
int socketdescriptor; // return-value of function socket
int socketoption; // return-value of function setsocketopt
int optionvalue = 1;
unsigned char message[102]; // will store the magic packet
unsigned char *message_ptr = message;
struct sockaddr_in socketaddress;
unsigned int socketport = 60000;
unsigned long broadcast = 0xFFFFFFFF;
ssize_t sendlength;
// Note these defines: AF_INET = IPV4; AF_INET6 = IPV6;
socketdescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (socketdescriptor < 0) {
write_logfile("Error: Socket for sending WOL could not be opened!\n", LOG_ERROR);
return SENDWOL_SOCKET_ERROR;
} else {
memset(message_ptr, 0xFF, 6); // copy 6 times 0xFF at in the beginning
message_ptr += 6; // step 6 bytes forward
for (tempint = 0; tempint < 16; ++tempint) {
memcpy(message_ptr, WOL_hex, 6);
message_ptr += 6;
} // end of for-loop
socketoption = setsockopt(socketdescriptor, SOL_SOCKET, SO_BROADCAST, &optionvalue, sizeof(optionvalue));
if (socketoption < 0) close(socketdescriptor); else {
socketaddress.sin_family = AF_INET;
socketaddress.sin_addr.s_addr = broadcast;
socketaddress.sin_port = htons(socketport);
sendlength = sendto(socketdescriptor,(char *)message, sizeof(message), 0, (struct sockaddr *)&socketaddress, sizeof(socketaddress));
if (sendlength < 0) {
write_logfile("Error: sending of WOL-command failed!\n", LOG_ERROR);
return SENDWOL_SEND_ERROR;
} else {
close(socketdescriptor);
}
} // end of sendding message out
} // end of setting socket option
return NOERROR;
} // end of sendWOL ***********************************************************************************************
unsigned int return_receiver_counter(const char* sender, const int inbound) {
unsigned int tempint;
switch (inbound) {
case MESSAGE_TYPE_SMS: for (tempint=cell_phone00_count;;tempint++) {
if (strcmp(sender, configvariables[tempint]) == 0) return tempint - cell_phone00_count;
} // end of for-loop
break;
case MESSAGE_TYPE_MAIL: for (tempint=mail_address_00_count;;tempint++) {
if (strcmp(sender, configvariables[tempint] ) == 0) return tempint - mail_address_00_count;
} // end of for-loop
break;
} // end of switch
return NOERROR;
} // end of return_receiver_counter *******************************************************************************
//*****************************************************************************************************************
// return_outbound_messagetype: we need to know several times the messagetype (sms, mail...) we have to use for sending back messages
// input: none because we use global variables
// returns: it returns the messagetype as an int
//*****************************************************************************************************************
unsigned int return_outbound_messagetype(void) {
if (outbound_sms_flag == TRUE) return MESSAGE_TYPE_SMS;
if (outbound_mail_flag == TRUE) return MESSAGE_TYPE_MAIL;
if (outbound_pushbullet_flag == TRUE) return MESSAGE_TYPE_PUSHBULLET;
return NOERROR;
} // end of return_outbound_messagetype
//*****************************************************************************************************************
// return_inbound_messagetype: we need to know several times the messagetype (sms, mail...) we have to use for receivng messages
// input: none because we use global variables
// returns: it returns the messagetype as an int
//*****************************************************************************************************************
unsigned int return_inbound_messagetype(void) {
if (inbound_sms_flag == TRUE) return MESSAGE_TYPE_SMS;
if (inbound_mail_flag == TRUE) return MESSAGE_TYPE_MAIL;
if (inbound_pushbullet_flag == TRUE) return MESSAGE_TYPE_PUSHBULLET;
return NOERROR;
} // end of return_inbound_messagetype
//*****************************************************************************************************************
// create_message_to_send: creates a text file which will be send out to cellphone (SMS), mailaddress (mail),
// pushbullet (sending a note)
// input: string which has to be send out; string which contains the address (cell-phone-#, mailaddress, pushbullet-address),
// type of inbound, type of outbound
// returncodes: MESSAGE_CREATE_OK = 0, MESSAGE_CREATE_FAIL = 1
//*****************************************************************************************************************
int create_message_to_send(const char* messagetosend, const char* receiver, const unsigned int inbound, const unsigned int outbound) {
FILE *messagefile; // the textfile which will contain the message we want to send out
char smsfilenamebegin[5 + 11 + 8 + 1] = "GSM1."; // filename will be like "GSM1.DD.MM.YYYY_HH:MM:SS", so this is the beginning of the filename
time_t timestamp_time;
struct tm *timestamp_tm;
char date_time[40] = "01.01.2000 01:01:01"; // string to save date + time, this is default-value
char pathtofile[125] = "\0"; // the path to the file we will create
char logentry[150]; // one line for the logfile
char mailcontent[250] = ""; // the content for the mail we will create
int randomnumber; // a random number
char randomnumberstring[6];
// int tempint;
char tempstring[200] = "";
switch (outbound) { // depending on the outbound we create our file
case MESSAGE_TYPE_SMS:
time(×tamp_time);
timestamp_tm = localtime( ×tamp_time);
strftime(date_time, 21, "%d.%m.%Y_%H:%M:%S_", timestamp_tm);
strcat(smsfilenamebegin, date_time);
strcpy(pathtofile, path_outgoing_SMS);
strcat(pathtofile, smsfilenamebegin);
srand(clock()); // initialize random generator
randomnumber = rand() / 1048576; // we need only a small number
sprintf(randomnumberstring, "%i", randomnumber);
strcat(pathtofile, randomnumberstring);
messagefile = fopen(pathtofile, "w+");
if ( messagefile != 0) {
strcpy(tempstring, configvariables[ return_receiver_counter(receiver, inbound) + cell_phone00_count]);
sprintf(logentry, "Info: outgoing SMS-file was created for # %s: %s\n", tempstring, pathtofile);
write_logfile(logentry, LOG_INFO);
sprintf(logentry, "To: %s\n\n%s", tempstring, messagetosend); // we build the complete message
fputs(logentry, messagefile);
fclose(messagefile);
return MESSAGE_CREATE_OK;
} else { // we could not open the outgoing message
sprintf(logentry, "Error: outgoing SMS-file could not be created: %s!\n", pathtofile);
write_logfile(logentry, LOG_ERROR);
return MESSAGE_CREATE_FAIL;
} // end of else
break;
case MESSAGE_TYPE_MAIL:
// we create the file which holds the mail-content:
messagefile = fopen(fullpath_outgoing_mail, "w+");
if (messagefile != 0) {
strcpy(tempstring, configvariables[ return_receiver_counter(receiver, inbound) + mail_address_00_count]);
sprintf(logentry, "Info: file for saving mail-content was created for %s: %s\n", tempstring, fullpath_outgoing_mail);
write_logfile(logentry, LOG_INFO);
sprintf(mailcontent, "To: %s\nSubject: %s\nMessage from message2action, see subject for details.", tempstring, messagetosend); // we build the complete mail-content
fputs(mailcontent, messagefile);
fclose(messagefile);
} else { // we could not open the file for creating + writing:
sprintf(logentry, "Error: file for saving mail-content could not be created: %s!\n", fullpath_outgoing_mail);
write_logfile(logentry, LOG_ERROR);
return MESSAGE_CREATE_FAIL;
}
break;
case MESSAGE_TYPE_PUSHBULLET: break;
} // end of switch-loop (outbound)
return NOERROR;
} // end of create_message_to_send ******************************************************************************
//*****************************************************************************************************************
// create_messages_to_send: creates a text file which will be send out to cellphone (SMS), mailaddress (mail),
// pushbullet (sending a note)
// input: string which has to be send out; string which contains the address (cell-phone-#, mailaddress, pushbullet-address),
// a counter which tells us how many messages we have to send, type of inbound, type of outbound
// returncodes: MESSAGE_CREATE_OK = 0, MESSAGE_CREATE_FAIL = 1
//*****************************************************************************************************************
int create_messages_to_send(const char* messagetosend, const char* receiver, const unsigned int messagecounter, const unsigned int inbound, const unsigned int outbound) {
FILE *messagefile; // the textfile which will contain the message we want to send out
FILE *shellskriptfile; // the file which will contain all the calls for sendging out mails with ssmtp
char smsfilenamebegin[5 + 11 + 8 + 1] = "GSM1."; // filename will be like "GSM1.DD.MM.YYYY_HH:MM:SS", so this is the beginning of the filename
time_t timestamp_time;
struct tm *timestamp_tm;
char date_time[40] = "01.01.2000 01:01:01"; // string to save date + time, this is default-value
char pathtofile[MAX_CHARS_PER_LINE_CONFIGFILE + 20] = "\0"; // the path to the file we will create
char logentry[150]; // one line for the logfile
char mailcontent[250] = ""; // the content for the mail we will create
int randomnumber; // a random number
char randomnumberstring[6];
char tempstring[200] = "";
unsigned int tempint;
switch (outbound) { // depending on the outbound we create our file
case MESSAGE_TYPE_SMS:
time(×tamp_time);
timestamp_tm = localtime( ×tamp_time);
strftime(date_time, 21, "%d.%m.%Y_%H:%M:%S_", timestamp_tm);
strcat(smsfilenamebegin, date_time);
strcpy(pathtofile, path_outgoing_SMS);
strcat(pathtofile, smsfilenamebegin);
srand(clock()); // initialize random generator
randomnumber = rand() / 1048576; // we need only a small number
sprintf(randomnumberstring, "%i", randomnumber);
strcat(pathtofile, randomnumberstring);
messagefile = fopen(pathtofile, "w+");
if ( messagefile != 0) {
strcpy(tempstring, configvariables[ return_receiver_counter(receiver, inbound) + cell_phone00_count]);
sprintf(logentry, "Info: outgoing SMS-file was created for # %s: %s\n", tempstring, pathtofile);
write_logfile(logentry, LOG_INFO);
sprintf(logentry, "To: %s\n\n%s", tempstring, messagetosend); // we build the complete message
fputs(logentry, messagefile);
fclose(messagefile);
return MESSAGE_CREATE_OK;
} else { // we could not open the outgoing message
sprintf(logentry, "Error: outgoing SMS-file could not be created: %s!\n", pathtofile);
write_logfile(logentry, LOG_ERROR);
return MESSAGE_CREATE_FAIL;
} // end of else
break;
case MESSAGE_TYPE_MAIL:
// we creat the file which holds the mail-content:
for (tempint = 0; tempint < messagecounter; tempint++) { // for every message we have to send out:
snprintf(tempstring, sizeof(tempstring), "%d", tempint);
strcpy(pathtofile, fullpath_outgoing_mail);
strcat(pathtofile, tempstring);
messagefile = fopen(pathtofile, "w+");
if (messagefile != 0) {
strcpy(tempstring, configvariables[ tempint + mail_address_00_count]);
sprintf(logentry, "Info: file for saving mail-content was created for %s: %s\n", tempstring, pathtofile);
write_logfile(logentry, LOG_INFO);
sprintf(mailcontent, "To: %s\nSubject: %s\n\nMessage from message2action, see subject for details.", tempstring, messagetosend); // we build the complete mail-content
fputs(mailcontent, messagefile);
fclose(messagefile);
} else { // we could not open the file for creating + writing:
sprintf(logentry, "Error: file for saving mail-content could not be created: %s!\n", fullpath_outgoing_mail);
write_logfile(logentry, LOG_ERROR);
return MESSAGE_CREATE_FAIL;
}
// we create the shell-file now which is called by systemd-timer in order to send out the mail with ssmtp.
// this is done only once at the beginning of the for-loop:
if (tempint == 0) {
shellskriptfile = fopen(fullpath_systemd_shell_mail, "w+");
if ( shellskriptfile != 0) { // if we could open a new file for saving shell-skript we add each call for ssmtp:
sprintf(logentry, "Info: shell skript for outgoing mail was created: %s\n", fullpath_systemd_shell_mail);
write_logfile(logentry, LOG_INFO);
fputs("#!/bin/bash\n", shellskriptfile); // we put this line only once in the shell-skript
} else { // end of if ( shellskriptfile != 0)
sprintf(logentry, "Error: shell skript for outgoing mail could not be created: %s!\n", fullpath_systemd_shell_mail);
write_logfile(logentry, LOG_ERROR);
return MESSAGE_CREATE_FAIL;
}
} // end of if (tempint == 0)
if ( shellskriptfile != 0) { // if we could open a new file for saving shell-skript we add each call for ssmtp:
sprintf(logentry, "%s -v %s < %s\n", fullpath_ssmtp, tempstring, pathtofile); // we build the complete message
fputs(logentry, shellskriptfile);
}
} // end of for (tempint = 0; tempint < messagecounter; tempint++)
fclose(shellskriptfile);
return MESSAGE_CREATE_OK;
break;
case MESSAGE_TYPE_PUSHBULLET: break;
} // end of switch-loop (outbound)
return NOERROR;
} // end of create_messages_to_send ******************************************************************************
//*****************************************************************************************************************
// check_onlinestatus: Check if an ip-address or a hostname is online via sending ping
// input: pingaddress : string of ip-address or hostname
// resultstring : save the resultmessage to this string
// returncodes: 0 = no error
// 1 = any error
//*****************************************************************************************************************
int check_onlinestatus(const char * pingaddress, char * resultstring) {
char logentry[256]; // one line in logfile
char pingcommand[256] = "/bin/ping -c 1 -w 2 "; // full programm to call with all parameters: -c : counter or retries, -w : timeout in seconds
char buffer[256] = ""; // buffer where the return-value of ping is saved
FILE *pipe; // pipe for saving return-value of ping
strcat(pingcommand, pingaddress);
strcat(pingcommand, " 2>&1"); // standout for errors should go on screen
pipe = popen(pingcommand, "r"); // open pipe for reading
if (pipe != 0) { // we could open the pipe
fgets(buffer, 256, pipe);
if ( strstr(buffer, "ping: unknown host") != 0) {
pclose(pipe);
sprintf(logentry, "Warning: %s is unknown.\n", pingaddress);
write_logfile(logentry, LOG_WARNING);
strcpy(resultstring, logentry);
return PING_UNKNOWN_HOST;
} else {
do { // we read from pipe until we have the line containing "% packet loss"
fgets(buffer, 256, pipe);
} while (strstr(buffer, "% packet loss") == 0);
// now we check if we have 0% packet loss or not:
if ( strstr(buffer, " 0%") != 0 ) {
pclose(pipe);
sprintf(logentry, "Info: %s is online.\n", pingaddress);
write_logfile(logentry, LOG_INFO);
strcpy(resultstring, logentry);
return PING_HOST_ONLINE;
} else {
pclose(pipe);
sprintf(logentry, "Info: %s is offline.\n", pingaddress);
write_logfile(logentry, LOG_INFO);
strcpy(resultstring, logentry);
return PING_HOST_OFFLINE;
}
}
pclose(pipe);
} else { // we could not open pipe
sprintf(logentry, "Error: could not open pipe for %s\n", pingcommand);
write_logfile(logentry, LOG_ERROR);
return PING_PIPE_ERROR;
}
} // end of function check_onlinestatus ****************************************************************
//*****************************************************************************************************************
// execute_command: performs the command we have found in message
// input: number of command we have found, the sender of the message
// returncodes: 0 = no error
// 1 = any error
//*****************************************************************************************************************
int execute_command(const int commandnumber, const char* sender_of_message) {
char logentry[200];
char tempchar[10];
char tempstring[100];
char online_result[100];
int errorcode; // returnvalue from a function called
switch (commandnumber) {
case messsagecommand_00_count : if (system(messsagecommand_00) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case messsagecommand_01_count : if (system(messsagecommand_01) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case messsagecommand_02_count : if (system(messsagecommand_02) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case messsagecommand_03_count : if (system(messsagecommand_03) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case messsagecommand_04_count : if (system(messsagecommand_04) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case messsagecommand_05_count : if (system(messsagecommand_05) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case messsagecommand_06_count : if (system(messsagecommand_06) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case messsagecommand_07_count : if (system(messsagecommand_07) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case messsagecommand_08_count : if (system(messsagecommand_08) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case messsagecommand_09_count : if (system(messsagecommand_09) != 0) {
strcpy(logentry, "Error: Command ");
strcat(logentry, configparameters[commandnumber]);
strcat(logentry, " = ");
strcat(logentry, configvariables[commandnumber]);
strcat(logentry, " could not be executed!\n");
write_logfile(logentry, LOG_ERROR);
} break;
case WOL_MAC_00_count: errorcode = sendWOL(WOL_MAC_00_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_00) != 0) {
strcpy(tempstring, hostname_00);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_00) != 0) {
strcpy(tempstring, ip_address_00);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_00_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
case WOL_MAC_01_count: errorcode = sendWOL(WOL_MAC_01_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_01) != 0) {
strcpy(tempstring, hostname_01);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_01) != 0) {
strcpy(tempstring, ip_address_01);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_01_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
case WOL_MAC_02_count: errorcode = sendWOL(WOL_MAC_02_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_02) != 0) {
strcpy(tempstring, hostname_02);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_02) != 0) {
strcpy(tempstring, ip_address_02);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_02_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
case WOL_MAC_03_count: errorcode = sendWOL(WOL_MAC_03_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_03) != 0) {
strcpy(tempstring, hostname_03);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_03) != 0) {
strcpy(tempstring, ip_address_03);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_03_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
case WOL_MAC_04_count: errorcode = sendWOL(WOL_MAC_04_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_04) != 0) {
strcpy(tempstring, hostname_04);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_04) != 0) {
strcpy(tempstring, ip_address_04);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_04_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
case WOL_MAC_05_count: errorcode = sendWOL(WOL_MAC_05_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_05) != 0) {
strcpy(tempstring, hostname_05);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_05) != 0) {
strcpy(tempstring, ip_address_05);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_05_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
case WOL_MAC_06_count: errorcode = sendWOL(WOL_MAC_06_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_06) != 0) {
strcpy(tempstring, hostname_06);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_06) != 0) {
strcpy(tempstring, ip_address_06);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_07_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
case WOL_MAC_07_count: errorcode = sendWOL(WOL_MAC_07_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_07) != 0) {
strcpy(tempstring, hostname_07);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_07) != 0) {
strcpy(tempstring, ip_address_07);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_07_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
case WOL_MAC_08_count: errorcode = sendWOL(WOL_MAC_08_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_08) != 0) {
strcpy(tempstring, hostname_08);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_08) != 0) {
strcpy(tempstring, ip_address_08);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_08_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
case WOL_MAC_09_count: errorcode = sendWOL(WOL_MAC_09_hex);
if (errorcode == NOERROR) { // we could send out WOL-command, now we check if device is online or not:
if (check_online_status_waittime_long != 0) {
sleep(check_online_status_waittime_long); // we have to wait for some time because the device might take some time to become online:
if ( strlen( hostname_09) != 0) {
strcpy(tempstring, hostname_09);
check_onlinestatus(tempstring, online_result);
} else
if ( strlen(ip_address_09) != 0) {
strcpy(tempstring, ip_address_09);
check_onlinestatus(tempstring, online_result);
}
// we send result back to outputchanel:
create_message_to_send(online_result, sender_of_message, return_inbound_messagetype(), return_outbound_messagetype());
} // if (check_online_status_waittime_long != 0)
} else { // we could not send out WOL-command:
sprintf(logentry, "Error: WOL could not be send out to %s!\n", WOL_MAC_09_hex);
write_logfile(logentry, LOG_ERROR);
}
break;
default: strcpy(logentry, "Error: Unknown command-# found: ");
sprintf(tempchar, "%d", commandnumber);
strcat(logentry, tempchar);
write_logfile(logentry, LOG_ERROR);
} // end of switch-loop
return NOERROR;
} // end of function execute_command *****************************************************************
//*****************************************************************************************************************
// install_signal_function: it installs a function in the handler-mechanism
//
// input: signal-#, function to install
// returncodes: 0 = OK, 1 = any error
//*****************************************************************************************************************
typedef void (*sighandler_t)(int);
int install_signal_function(int signal_number, sighandler_t signalhandler) {
struct sigaction new_signal;
new_signal.sa_handler = signalhandler;
sigemptyset(&new_signal.sa_mask);
new_signal.sa_flags = SA_RESTART;
if (sigaction(signal_number, &new_signal, NULL) < 0) return 1; else return 0;
} // end of function install_signal_function
//*****************************************************************************************************************
// check_signal: This function will be installed as the handler for signals we are receiving. Or in other words: When we get
// a signal like ctrl-c then this function will called and we can react on ctrl-c or even kill.
// input: signal-#
// returncodes: none
//*****************************************************************************************************************
static void check_signal(int signal_nr) {
if (signal_nr == SIGINT) write_logfile("Info: signal SIGINT was received.\n", LOG_INFO);
if (signal_nr == SIGTERM) write_logfile("Info: signal SIGTERM was received.\n", LOG_INFO);
processingflag = FALSE; // we have to tell the function startprocessing that we have to stop now
} // end of function check_signal ****************************************************************
//*****************************************************************************************************************
// check_smssender: checks if the sender of the SMS is valid. It compares the phone number with all configured phone-numbers in ini-file.
// input: string which contains the phonenumber
// returncodes: SMS_SENDER_VALID = 0, SMS_SENDER_NOTVALID = 1
//*****************************************************************************************************************
int check_smssender(const char* smssender) {
int temp = 0;
int validflag = FALSE; // this variable is per default FALSE and will either be changed to TRUE or it remains FALSE
for (temp = cell_phone00_count; temp < cell_phone09_count; ++temp) { // we step through all configured cell phone numbers
if (strcmp(smssender, configvariables[temp]) == 0 ) { validflag = TRUE; temp = cell_phone09_count; }
}
if (validflag == TRUE) return SMS_SENDER_VALID; else return SMS_SENDER_NOTVALID;
} // end of check_smssender **********************************************************************************
//*****************************************************************************************************************
// check_mailsender: checks if the sender of the SMS is valid. It compares the phone number with all configured phone-numbers in ini-file.
// input: string which contains the mailaddress
// returncodes: MAIL_SENDER_VALID = 0, MAIL_SENDER_NOTVALID = 1
//*****************************************************************************************************************
int check_mailsender(const char* mailsender) {
int temp = 0;
int validflag = FALSE; // this variable is per default FALSE and will either be changed to TRUE or it remains FALSE
for (temp = mail_address_00_count; temp < mail_address_09_count; ++temp) { // we step through all configured cell phone numbers
if (strcmp(mailsender, configvariables[temp]) == 0 ) { validflag = TRUE; temp = mail_address_09_count; }
}
if (validflag == TRUE) return MAIL_SENDER_VALID; else return MAIL_SENDER_NOTVALID;
} // end of check_mailsender **********************************************************************************
//*****************************************************************************************************************
// return_cellphonenumber_from_inifile: returns the first valid cell-phone-#. This number will be written in stop-message
// input: string which contains the phonenumber we will return
// returncodes: CELL_PHONE_FOUND = 0, CELL_PHONE_NOT_FOUND = 1
//*****************************************************************************************************************
int return_cellphonenumber_from_inifile(char* cellphonenumber) {
int temp = 0;
int validflag = FALSE; // this variable is per default FALSE and will either be changed to TRUE or it remains FALSE
for (temp = cell_phone00_count; temp < cell_phone09_count; ++temp) { // we step through all configured cell phone numbers
if (strlen(configvariables[temp]) != 0 ) {
validflag = TRUE;
strcpy(cellphonenumber, configvariables[temp]);
temp = cell_phone09_count;
} // we have found a cell-phone-#, we stop searching
}
if (validflag == TRUE) return CELL_PHONE_FOUND; else {
strcpy(cellphonenumber, "DUMMY"); // we copy DUMMY to cell-phone-number because we do not have a valid cell-phone-#
return CELL_PHONE_NOT_FOUND;
}
return NOERROR;
} // end of return_cellphonenumber_from_inifile
//*****************************************************************************************************************
// return_mailaddress_from_inifile: returns the first valid mailaddress from ini-file. This mailaddress will be written in stop-message
// input: string which contains the mailaddress we will return
// returncodes: MAIL_ADDRESS_FOUND = 0, MAIL_ADDRESS_NOT_FOUND = 1
//*****************************************************************************************************************
int return_mailaddress_from_inifile(char* mailaddress) {
int temp = 0;
int validflag = FALSE; // this variable is per default FALSE and will either be changed to TRUE or it remains FALSE
for (temp = mail_address_00_count; temp < mail_address_09_count; ++temp) { // we step through all configured mailaddresses
if (strlen(configvariables[temp]) != 0 ) {
validflag = TRUE;
strcpy(mailaddress, configvariables[temp]);
temp = mail_address_09_count;
} // we have found a mailaddress, we stop searching
}
if (validflag == TRUE) return MAIL_ADDRESS_FOUND; else {
strcpy(mailaddress, "DUMMY"); // we copy DUMMY to cell-phone-number because we do not have a valid cell-phone-#
return MAIL_ADDRESS_NOT_FOUND;
}
return NOERROR;
} // end of return_mailaddress_from_inifile
//*****************************************************************************************************************
// get_command_from_sms: extracts the command from a sms we have received
// input: the file we have opened. The command will be written to commandstring)
// returncodes: 0 = no error
// 1 = any error
//*****************************************************************************************************************
unsigned int get_command_from_sms(FILE *smsfilep, char *commandstring, char *smssender) {
char from_toa[50];
char from_SMSC[20];
char send_date[17]; // format: <2 digits of year>-<month>-<date of month> hh:mm:11
char received_date[17];
char subject[10];
char modem[10];
char IMSI[20];
char report[4];
char alphabet[10];
char *charNL;
unsigned int tempint;
char logentry[200] = ""; // one line we write to logfile
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #1 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(smssender, commandstring + 6); // we get "From: "
if (check_smssender(smssender) == SMS_SENDER_NOTVALID) { // we check if we have received a SMS from a valid cell phone
sprintf(logentry, "Warning: invalid sender-phonenumber in incoming SMS: %s!\n", smssender);
write_logfile(logentry, LOG_WARNING);
// now we send to all valid cell-phones a warning message:
for (tempint = cell_phone00_count; tempint < cell_phone09_count; tempint++) {
if (strlen(configvariables[tempint]) != 0 ) // if we have a cell-phone configured we send to the # the warning
create_message_to_send(logentry, configvariables[tempint], return_inbound_messagetype(), return_outbound_messagetype()); // we create a SMS with a message to a cell-phone-#
} // end of for-loop
// now we exit here because we have an invalid phonenumber:
return SMS_SENDER_NOTVALID;
} else { // the sender-phone-# is valid, we continue to read the whole incoming file:
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #2 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(from_toa, commandstring + 10); // we skip "From_TOA: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #3 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(from_SMSC, commandstring + 11); // we skip "From_SMSC: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #4 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(send_date, commandstring + 6); // we skip "Sent: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #5 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(received_date, commandstring + 10); // we skip "Received: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #6 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(subject, commandstring + 9); // we skip "Subject: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #7 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(modem, commandstring + 7); // we skip "Modem: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #8 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(IMSI, commandstring + 6); // we skip "IMSI: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #9 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(report, commandstring + 8); // we skip "Report: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #10 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(alphabet, commandstring + 8); // we skip "Alphabet: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #11 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(alphabet, commandstring + 8); // we skip "Length: "
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #12 from file in temp
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, smsfilep); // save line #13 from file in temp, this is the content where we expect to get the command from as written in the SMS file
upcase_string(commandstring); // all chars to upper case
#ifdef DEVSTAGE
sprintf(logentry, "Info: content of last line in SMS-file: %s\n", commandstring);
write_logfile(logentry, LOG_INFO);
#endif
}
return NOERROR;
} // end of function get_command_from_sms ****************************************************************
//*****************************************************************************************************************
// get_command_from_mail: extracts the command from a mail we have received
// input: the file we have opened; the found command will be written to commandstring; the mailaddress of the sender
// returncodes: NOERROR = no error
// MAIL_SENDER_NOTVALID = we have received a mail from an account we do not know
//*****************************************************************************************************************
unsigned int get_command_from_mail(FILE *mailfilep, char *commandstring, char *mailsender) {
char subject[160] = "";
char mailaddress[160] = "";
char *charNL;
char *char_smaleras; // smaleras = "<"
char *char_biggeras; // smaleras = ">"
char *char_nl; // new line
unsigned int tempint;
unsigned int valid_mail_address_counter = 0; // how many valid mail-addresses do we have?
char logentry[200] = ""; // one line we write to logfile
fgets(commandstring, MAX_CHARS_PER_LINE_CONFIGFILE, mailfilep); // save line #1 from file in temp
charNL = strchr(commandstring, '\n');
*charNL = '\0'; // terminate temp string
strcpy(mailaddress, commandstring + 6); // we get "From: ", but we have to get the value in angle-brackets:
char_smaleras = strchr(mailaddress, '<');
char_biggeras = strchr(mailaddress, '>');
if ( (char_smaleras != NULL) && (char_biggeras != NULL)) {
strncpy(mailsender, char_smaleras + 1, char_biggeras - char_smaleras - 1);
mailsender[char_biggeras - char_smaleras - 1] = '\0'; // we terminate the string
upcase_string(mailsender); // we change all chars to upcase
} else { // we have either no '<' or no '>' in the mailaddress, we can stop with this file:
sprintf(logentry, "Error: sending mailaddres is not valid: it must contain '<' and '>'!\n");
write_logfile(logentry, LOG_WARNING);
return MAIL_SENDER_NOTVALID;
}
if (check_mailsender(mailsender) == MAIL_SENDER_NOTVALID) { // we check if we have received a mail from a valid mailaddress
sprintf(logentry, "Warning: invalid mailaddress in incoming mail: %s!\n", mailsender);
write_logfile(logentry, LOG_WARNING);
// now we send to all configured mails-addresses a warning message. First we count how many addresses we have:
for (tempint = mail_address_00_count; tempint < mail_address_09_count; tempint++) {
if (strlen(configvariables[tempint]) != 0 ) valid_mail_address_counter++; // if we have a mail-address configured we send to the mail-address the warning
} // end of for-loop
create_messages_to_send(logentry, configvariables[mail_address_00_count], valid_mail_address_counter, return_inbound_messagetype(), return_outbound_messagetype()); // we create a mail with a message to a mailaddress
// now we exit here because we have an invalid mail-address:
return MAIL_SENDER_NOTVALID;
} else { // the mailaddress is valid, we continue to read the whole incoming file:
fgets(subject, MAX_CHARS_PER_LINE_CONFIGFILE, mailfilep); // save line #2 from file in temp
strcpy(commandstring, subject + 9); // we skip "Subject: " in the read line from the file
char_nl = strchr(commandstring, '\n');
*char_nl = '\0'; // we replace the newline-char with a '\0'
upcase_string(commandstring); // we change all chars to upcase
}
return NOERROR;
} // end of function get_command_from_mail ****************************************************************
//*****************************************************************************************************************
// get_command_from_pushbullet: extracts the command from a sms we have received
// input: the file we have opened. The command will be written to commandstring)
// returncodes: 0 = no error
// 1 = any error
//*****************************************************************************************************************
unsigned int get_command_from_pushbullet(FILE *smsfilep, char *commandstring, char *mailaddress) {
if (smsfilep == NULL) smsfilep = NULL;
if (mailaddress == NULL) mailaddress = NULL;
if (commandstring == NULL) commandstring = NULL;
return NOERROR;
} // end of function get_command_from_pushbullet ****************************************************************
//*****************************************************************************************************************
// send_signal_keyboard_hit: checks if user hit a key on the keyboard
// input: process-id of own program
// returncodes: # of allowed parameters
//*****************************************************************************************************************
void send_signal_keyboard_hit(int *process_id) {
int readchar;
int buffered_charackter = 0;
while (buffered_charackter == 0) {
ioctl(STDIN_FILENO, FIONREAD, &buffered_charackter); // we check if we have something in the buffer because user hit the keyboard
usleep(1000*100); // 1 second = 1000 * 1000 mikroseconds
}
readchar = getchar(); // we get the sign from the buffer so that buffer is empty when program ends
if (readchar == 'c') readchar = 'c'; // this is needed to suppress a warning from compiler like "warning: unused variable readchar"
kill(*process_id, SIGTERM); // now we send the signal to end the program; Note: c-function raise did not work. And I don't know why.
} // end of check_keyboard_hit *****************************************************
//*****************************************************************************************************************
// start_processing_message: starts to process incoming SMS-messages and mails. Function loops until file with stop-SMS will be
// found or signal to terminate will be received
// input: type of message (SMS, mail, pushbullet ...) for inbound and for outbound
// returncodes: 0 = no error
// 1 = any error
//*****************************************************************************************************************
int start_processing_message(const int inbound) {
DIR *incomingdirectoryp;
struct dirent *directoryentryp;
struct stat fileattributes;
FILE *messagefilep; // file which contains the message (SMS, mail, pushbullet ...)
FILE *processedmessagefilep; // file in "processed" directory
FILE *processidfilep; // file-handler which contains the process-id of our programm
int processid; // the ID of our processs
char fullpathincomingfile[MAX_CHARS_PER_LINE_CONFIGFILE];
char messagefilename[MAX_CHARS_PER_LINE_CONFIGFILE] = "";
char tempstring[MAX_CHARS_PER_LINE_CONFIGFILE];
int tempint;
char *tempsms; // this pointer will be used to allocate memory for the copy-job of the sms-file
// const char sudo_rm_const[] = "sudo rm ";
// char remove_command[256] = ""; // complete command which is called to remove the incoming message-file
int commandfoundflag = FALSE; // indicates that we have found the parameter in the SMS in our list of commands
char logentry[200] = ""; // one line we write to logfile
char online_result[200] = ""; // the result of the online-check is saved here
unsigned int loopcounter = 0; // counts how many times we were waiting for next message since start of program
unsigned int processed_sms_counter = 0; // counts # of processed SMS-files
unsigned int processed_mail_counter = 0; // counts # of processed mail-files
unsigned int processed_pushbullet_counter = 0; // counts # of processed pushbullet-files
pthread_t keyboardcheck_thread; // pointer to the thread which checks if user hit the keyboard
char messagesender[50] = ""; // holds the sender like phone-# for sms and mailaddress
static struct termios temp_terminal; // temporary terminal settings
static struct termios current_terminal; // current terminal setting
if (read_config_file(config_filename) != NOERROR) return CONFIG_FILE_READ_ERROR; // if anything went wrong with reading the configfile we stop now, error-messages are printed on screen
write_logfile("Info: we start processing now.\n", LOG_INFO);
printf("Press any readable key (ESC or spacebar) to stop program.\n");
processid = getpid(); // we get our process-ID so that we can write it to a file and start our keyboard threat
// tempint=0;
tempint = pthread_create(&keyboardcheck_thread, NULL, (void *)&send_signal_keyboard_hit, &processid);
if(tempint != 0) { // we start the thread which listens to keyboard
printf ("Error: Thread for listening to keyboard could not be started!\n");
return KEYBOARD_THREAD_ERROR;
}
// now we save the process-id to a file. This is used to send to this process the "SIGTERM" signal
switch (inbound) {
case MESSAGE_TYPE_SMS: processidfilep = fopen(fullpath_smsfile_PID, "wb" ); break;
case MESSAGE_TYPE_MAIL: processidfilep = fopen(fullpath_mailfile_PID, "wb" ); break;
case MESSAGE_TYPE_PUSHBULLET: processidfilep = fopen(fullpath_pushbulletfile_PID, "wb" ); break;
} // end of switch-loop
if (processidfilep != 0) {
fwrite(&processid, sizeof(processid), 1, processidfilep);
fclose(processidfilep);
sprintf(logentry, "Info: own process-id: %d\n", processid);
write_logfile(logentry, LOG_INFO);
if (install_signal_function(SIGTERM, check_signal) == 1 ) write_logfile("Error: signalhandler for SIGTERM could not be installed!\n", LOG_ERROR);
else write_logfile("Info: signalhandler was installed for signal SIGTERM.\n", LOG_INFO);
switch (inbound) {
case MESSAGE_TYPE_SMS: incomingdirectoryp = opendir(configvariables[path_incoming_SMS_count]); // we open the directory where we expect the incoming SMS-textfile to be
strcpy(fullpathincomingfile, configvariables[path_incoming_SMS_count]);
strcpy(tempstring, configvariables[path_processed_SMS_count]);
tempstring[strlen(configvariables[path_processed_SMS_count])] = '\0'; // we have to replace the '\n' with '\0'
break;
case MESSAGE_TYPE_MAIL: incomingdirectoryp = opendir(configvariables[path_incoming_mail_count]); // we open the directory where we expect the incoming mails to be
strcpy(fullpathincomingfile, configvariables[path_incoming_mail_count]);
strcpy(tempstring, configvariables[path_processed_mail_count]);
tempstring[strlen(configvariables[path_processed_mail_count])] = '\0'; // we have to replace the '\n' with '\0'
break;
case MESSAGE_TYPE_PUSHBULLET: incomingdirectoryp = opendir(configvariables[path_incoming_pushbullet_count]); // we open the directory where we expect the incoming mails to be
strcpy(fullpathincomingfile, configvariables[path_incoming_pushbullet_count]);
strcpy(tempstring, configvariables[path_processed_pushbullet_count]);
tempstring[strlen(configvariables[path_processed_pushbullet_count])] = '\0'; // we have to replace the '\n' with '\0'
break;
} // end of switch-loop
if ( incomingdirectoryp != 0) { // we can open the directory for reading in it
tempint = tcgetattr (STDIN_FILENO, ¤t_terminal); // we save terminal-settings in variable current_terminal
if (tempint == -1) write_logfile("Error: Terminalsettings could not be determined!\n", LOG_ERROR);
temp_terminal = current_terminal; // we save the current settings to temp-variable
// we change some flags on the temporary terminalsettings:
temp_terminal.c_iflag = temp_terminal.c_iflag & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
temp_terminal.c_oflag = temp_terminal.c_iflag & ~(OPOST);
temp_terminal.c_cflag = temp_terminal.c_cflag & ~(CSIZE | PARENB);
temp_terminal.c_lflag = temp_terminal.c_lflag & ~(ECHO|ICANON|IEXTEN|ISIG);
temp_terminal.c_cflag = temp_terminal.c_cflag | CS8;
temp_terminal.c_cc[VMIN] = 1;
temp_terminal.c_cc[VTIME] = 0;
tempint = tcsetattr (STDIN_FILENO, TCSAFLUSH, &temp_terminal); // we change now our terminal-settings
if (tempint == -1) write_logfile("Error: Terminalsettings could not be set to new values!\n", LOG_ERROR);
while (processingflag == TRUE) {
directoryentryp = readdir(incomingdirectoryp);
if (directoryentryp != 0) {
switch (inbound) {
case MESSAGE_TYPE_SMS: strcpy(fullpathincomingfile, configvariables[path_incoming_SMS_count]);
strcpy(tempstring, configvariables[path_processed_SMS_count]);
tempstring[strlen(configvariables[path_processed_SMS_count])] = '\0'; // we have to replace the '\n' with '\0'
break;
case MESSAGE_TYPE_MAIL: strcpy(fullpathincomingfile, configvariables[path_incoming_mail_count]);
strcpy(tempstring, configvariables[path_processed_mail_count]);
tempstring[strlen(configvariables[path_processed_mail_count])] = '\0'; // we have to replace the '\n' with '\0'
break;
case MESSAGE_TYPE_PUSHBULLET: strcpy(fullpathincomingfile, configvariables[path_incoming_pushbullet_count]);
strcpy(tempstring, configvariables[path_processed_pushbullet_count]);
tempstring[strlen(configvariables[path_processed_pushbullet_count])] = '\0'; // we have to replace the '\n' with '\0'
break;
} // end of switch-loop
strcpy(messagefilename, directoryentryp->d_name);
strcat(fullpathincomingfile, messagefilename);
tempint = stat(fullpathincomingfile, &fileattributes); // we get attributes of the file we have
tempint = S_ISREG(fileattributes.st_mode); // we check if the file is a regular file: value unequal 0 means we have a regular file
if (tempint != 0) { // if the found file is a really a file and not something else
sprintf(logentry, "Info: incoming filename: %s\n", fullpathincomingfile);
write_logfile(logentry, LOG_INFO);
loopcounter = 0;
messagefilep = fopen(fullpathincomingfile, "r");
if (messagefilep == 0) {
sprintf(logentry, "Error: file %s could not be opened for reading!\n", fullpathincomingfile);
write_logfile(logentry, LOG_ERROR);
fclose(messagefilep);
} else { // we start to read the incoming file:
strcat(tempstring, messagefilename);
sprintf(logentry, "Info: new filename for saving processed file: %s\n", tempstring);
write_logfile(logentry, LOG_INFO);
processedmessagefilep = fopen(tempstring, "w"); // we open file for saving content in new file
if (processedmessagefilep == 0) {
sprintf(logentry, "Error: file %s could not be opened for saving content in new file!\n", tempstring);
write_logfile(logentry, LOG_ERROR);
// we stop now with processing:
processingflag = FALSE;
} else { // we will get the command from the message. Each message looks different:
switch (inbound) {
case MESSAGE_TYPE_SMS: tempint = get_command_from_sms(messagefilep, tempstring, messagesender); ++processed_sms_counter;
break;
case MESSAGE_TYPE_MAIL: tempint = get_command_from_mail(messagefilep, tempstring, messagesender); ++processed_mail_counter;
break;
case MESSAGE_TYPE_PUSHBULLET: tempint = get_command_from_pushbullet(messagefilep, tempstring, messagesender); ++processed_pushbullet_counter;
break;
} // end of switch-loop
if (tempint == NOERROR) {
// now we have to find out which command we have. We compare at first step the found command with our build-in-commands:
if ( strstr(tempstring, message2action_stop_command) != 0) { // we found the parameter, we can stop for searching
sprintf(logentry, "Info: Command found in message-file: %s\n", tempstring);
write_logfile(logentry, LOG_INFO);
commandfoundflag = TRUE;
processingflag = FALSE;
write_logfile("Info: programm will be stopped now.\n", LOG_INFO);
}
if ( strstr(tempstring, reboot_pi_command) != 0) { // we found the parameter, we can stop for searching
sprintf(logentry, "Info: Command found in message-file: %s\n", tempstring);
write_logfile(logentry, LOG_INFO);
commandfoundflag = TRUE;
processingflag = FALSE;
reboot_piflag = TRUE;
write_logfile("Info: computer will be rebooted now.\n", LOG_INFO);
sync();
system("shutdown -r now");
}
if ( strstr(tempstring, shutdown_pi_command) != 0) { // we found the parameter, we can stop for searching
sprintf(logentry, "Info: Command found in message-file: %s\n", tempstring);
write_logfile(logentry, LOG_INFO);
commandfoundflag = TRUE;
processingflag = FALSE;
shutdown_piflag = TRUE;
write_logfile("Info: computer will be shutdown now.\n", LOG_INFO);
sync();
system("shutdown -h now");
}
if ( strstr(tempstring, status_pi_command) != 0) { // we found the parameter, we can stop for searching
sprintf(logentry, "Info: Command found in message-file: %s\n", tempstring);
write_logfile(logentry, LOG_INFO);
commandfoundflag = TRUE;
processingflag = TRUE;
shutdown_piflag = FALSE;
sprintf(logentry, "Info: # of processed SMS: %d, mails: %d, errors: %d, warnings: %d\n", processed_sms_counter, processed_mail_counter, errorcounter, warningcounter);
write_logfile("Info: we send status back to sender.\n", LOG_INFO);
write_logfile(logentry, LOG_INFO);
create_message_to_send(logentry, messagesender, return_inbound_messagetype(), return_outbound_messagetype()); // we send message to sender with the status : it depends on the outbound
// create_sms_to_send(logentry, messagesender); // we send SMD to sender with the status
}
if (strstr(tempstring, online_status_command_suffix) != 0) { // we found parameter for checking onlinestatus, we have to check now, if we have one of our WOL-addresses
if ( strncmp("WOL", tempstring, 3) == 0) { // if first 3 chars are equal to "WOL" we have a request for checking online-status:
sprintf(logentry, "Info: Command found in message-file: %s\n", tempstring);
write_logfile(logentry, LOG_INFO);
commandfoundflag = TRUE;
processingflag = TRUE;
shutdown_piflag = FALSE;
tempstring[5] = '\0'; // now we terminate the received command before the status-command
// now we check the online-status of the device. We have to search the IP-address or hostname:
tempint = atoi(tempstring + 3); // we convert the last 2 digits of the command in an integer
// now we know which hostname or IP-address we have to check.
if ( strlen( configvariables[tempint + hostname_00_count]) != 0) {
strcpy(tempstring, configvariables[tempint + hostname_00_count]);
tempint = check_onlinestatus(tempstring, online_result);
} else
if ( strlen(configvariables[tempint + ip_address_00_count]) != 0) {
strcpy(tempstring, configvariables[tempint + ip_address_00_count]);
tempint = check_onlinestatus(tempstring, online_result);
} else { // we have an error: neither IP-address nor hostname is in ini-file
sprintf(logentry, "Error: neither IP-address nor hostname in ini-file for %s\n", tempstring);
write_logfile(logentry, LOG_ERROR);
}
// we send result back to outputchanel:
create_message_to_send(online_result, messagesender, return_inbound_messagetype(), return_outbound_messagetype());
} // if (strncmp("WOL", tempstring, 3) == 0)
} // if (strstr(online_status_command_suffix, tempstring) != 0)
if (commandfoundflag == FALSE) { // we search for the command only when we did not recognize an internal command:
for (tempint = messsagecommand_00_count; tempint < configparametercount; tempint++) {
if ( strstr(tempstring, configparameters[tempint]) != 0) { // we found the parameter, we can stop for searching
sprintf(logentry, "Info: Command number %d to be executed: %s\n", tempint, configparameters[tempint]);
write_logfile(logentry, LOG_INFO);
execute_command(tempint, messagesender); // now we execute the command we have found
tempint = configparametercount; // we end here with the for-loop
commandfoundflag = TRUE;
} else { // we did not find the command
if ( (commandfoundflag == FALSE) && (tempint == configparametercount -1 )) {
sprintf(logentry, "Error: unknown command in message-file: %s\n", tempstring);
write_logfile(logentry, LOG_ERROR);
}
}
} // end of for loop
} // end of (commandfoundflag == FALSE)
} // end of if (tempint == NOERROR)
// we copy complete file-content from the incoming directory to the processed directory, we don't need the file anymore:
#ifdef DEVSTAGE
sprintf(logentry, "Info: Copy of received message-file starts now.\n");
write_logfile(logentry, LOG_INFO);
#endif
rewind(messagefilep);
#ifdef DEVSTAGE
sprintf(logentry, "Info: filesize of message-file: %i\n", (int)fileattributes.st_size);
write_logfile(logentry, LOG_INFO);
#endif
tempsms = malloc(fileattributes.st_size + 1); // we need memory to read the whole sms-file into
sprintf(logentry, "Info: number of chars read: %d\n", fread(tempsms, 1, fileattributes.st_size, messagefilep));
#ifdef DEVSTAGE
write_logfile(logentry, LOG_INFO);
#endif
tempsms[fileattributes.st_size] = '\0';
sprintf(logentry, "Info: number of chars written: %d\n", fwrite(tempsms, 1, fileattributes.st_size, processedmessagefilep));
#ifdef DEVSTAGE
write_logfile(logentry, LOG_INFO);
#endif
free(tempsms);
sprintf(logentry, "Info: returncode for closing processed message-file: %d\n", fclose(processedmessagefilep));
#ifdef DEVSTAGE
write_logfile(logentry, LOG_INFO);
#endif
fclose(messagefilep); // we close the sourcefile
// strcat(remove_command, sudo_rm_const); // we initialize the command-value
// strcat(remove_command, fullpathincomingfile); // we add the filename of the incoming SMS-file to the rm-command
if (remove(fullpathincomingfile) != 0) { // now we remove the source-file because we have a copy in processed-directory
sprintf(logentry, "Error: received message-file could not be deleted!\n");
write_logfile(logentry, LOG_ERROR);
} else
write_logfile("Info: received message-file was deleted successfully.\n", LOG_INFO);
// remove_command[0] = '\0'; // we initialise the remove-command
commandfoundflag = FALSE; // we reset the flag
} // end of if (processedsmsfilep == 0)
} // if (smsfilep == 0)
} // end of if concerning "." and ".." in filename
} else { // we are at end of directory
closedir(incomingdirectoryp);
switch (inbound) {
case MESSAGE_TYPE_SMS : incomingdirectoryp = opendir(configvariables[path_incoming_SMS_count]);
sprintf(logentry, "Info: wait-cycle # %d, wait until next sms is received: %lu seconds\n", ++loopcounter, wait_time_next_sms_long);
write_logfile( logentry, LOG_INFO);
sleep(wait_time_next_sms_long); // we wait for some seconds until the next message comes in:
break; // we open the directory again
case MESSAGE_TYPE_MAIL : incomingdirectoryp = opendir(configvariables[path_incoming_mail_count]);
sprintf(logentry, "Info: wait-cycle # %d, wait until next mail is received: %lu seconds\n", ++loopcounter, wait_time_next_mail_long);
write_logfile( logentry, LOG_INFO);
sleep(wait_time_next_mail_long); // we wait for some seconds until the next message comes in:
break; // we open the directory again
case MESSAGE_TYPE_PUSHBULLET : incomingdirectoryp = opendir(configvariables[path_incoming_mail_count]);
sprintf(logentry, "Info: wait-cycle # %d, wait until next pushbulet is received: %lu seconds\n", ++loopcounter, wait_time_next_pushbullet_long);
write_logfile( logentry, LOG_INFO);
sleep(wait_time_next_pushbullet_long); // we wait for some seconds until the next message comes in:
break; // we open the directory again
} // end of switch-loop
} // we finished waiting for next message
} // end of while-loop for checking processingflag == TRUE
tempint = tcsetattr (STDIN_FILENO, TCSANOW, ¤t_terminal); // we set back our current terminal to old mode
} else { // we could not open the incoming directory for reading in it
sprintf(logentry, "Error: directory %s could not be opened for reading incoming message-files!\n", configvariables[path_incoming_SMS_count]);
write_logfile(logentry, LOG_ERROR);
}
// we are at end of the loop and we will stop now, we have to delete the file containing the process-id:
switch (inbound) {
case MESSAGE_TYPE_SMS: tempint = remove(fullpath_smsfile_PID); strcpy(tempstring, fullpath_smsfile_PID); break;
case MESSAGE_TYPE_MAIL: tempint = remove(fullpath_mailfile_PID); strcpy(tempstring, fullpath_mailfile_PID); break;
case MESSAGE_TYPE_PUSHBULLET: tempint = remove(fullpath_pushbulletfile_PID); strcpy(tempstring, fullpath_pushbulletfile_PID); break;
} // end of switch-loop
if (tempint != 0) {
sprintf(logentry, "Error: file for saving process-ID could not be deleted: %s\n", tempstring);
write_logfile(logentry, LOG_ERROR);
}
} else { // we could not create PID file for saving process-ID
// printf("Error: PID-file could not be created!\n");
strcpy(logentry, "Error: PID-file could not be created!\n");
write_logfile(logentry, LOG_ERROR);
}
write_logfile("Info: we stop processing now.\n", LOG_INFO);
return NOERROR;
} // end of function start_processing_message ****************************************************************
//*****************************************************************************************************************
// stop_processing_message: stops processing incoming messages. It simply creates SMS-message which contains the command for stopping.
// or in other words: it emulates that we received a message with the stop-command
// input: none
// returncodes: 0 = no error
// 1 = any error
//*****************************************************************************************************************
int stop_processing_message(const unsigned int inboundtype) {
FILE *filep; // file which contains the SMS we will fill with content
char stopfile[MAX_CHARS_PER_LINE_CONFIGFILE]; // filename of the file which will contain the stop message
char From_line[100] = "";
char logentry[200] = "";
FILE *processidfilep;
int processid = 0;
int killreturnvalue; // return value of function kill
if (read_config_file(config_filename) == NOERROR) { // we read from config-file the cell phone number which is allowed to send SMS
// first we distinguish between our inbounds (sms, mail, ...) and then we distinguish between our stoppping method (file, signal)
switch (inboundtype) {
case MESSAGE_TYPE_SMS :
if ( stopfile_flag == STOPFILE_TRUE ) {
strcpy(stopfile, configvariables[path_incoming_SMS_count]); // we get the path were the incoming SMS will be written in
strcat(stopfile, configvariables[message2action_stop_filename_count]);
sprintf(logentry, "Info: filename for STOP-SMS: %s\n", stopfile);
write_logfile(logentry, LOG_INFO);
filep = fopen(stopfile, "w+");
if ( filep != 0 ) {
return_cellphonenumber_from_inifile(logentry); // we get first valid cell-phone-# from ini-file
sprintf(From_line, "From: %s", logentry);
#ifdef DEVSTAGE
sprintf(logentry, "Info: 1. line in STOP-SMS-file: %s\n", From_line);
write_logfile(logentry, LOG_INFO);
#endif
fputs(From_line, filep);
// the following string is constant, none of the values will be read:
fputs("\nFrom_TOA: DUMMY\nFrom_SMSC: DUMMY\nSent: DUMMY\nSubject: DUMMY\nModem: DUMMY\nIMSI: DUMMY\nReport: DUMMY\nAlphabet: DUMMY\nLength: DUMMY\n\n", filep);
fputs(configvariables[message2action_stop_command_count], filep); // we take the stop-command from the ini-file
#ifdef DEVSTAGE
write_logfile("Info: dummy-line written to STOP-SMS-file.\n", LOG_INFO);
#endif
fclose(filep);
write_logfile("Info: STOP-SMS-file successfully written and closed.\n", LOG_INFO);
} else { // we could not open file for creating stop-sms-file
sprintf(logentry, "Error: file %s could not be opened for writing STOP-SMS-file!\n", stopfile);
write_logfile(logentry, LOG_ERROR);
}
} // end of if (stoppingmethod == STOPFILE_TRUE)
if (stopsignal_flag == STOPSIGNAL_TRUE) {
processidfilep = fopen(fullpath_smsfile_PID, "rb" );
if (processidfilep != NULL) { // we could open the pid-file
fread(&processid, sizeof(processid), 1, processidfilep);
fclose(processidfilep);
sprintf(logentry, "Info: read process-ID: %d\n", processid);
write_logfile(logentry, LOG_INFO);
killreturnvalue = kill(processid, SIGTERM);
if (killreturnvalue == 0) { // we could send signal to process
sprintf(logentry, "Info: SIGTERM was send to process # %d\n", processid);
write_logfile(logentry, LOG_INFO);
} else { // we could not send signal to process
sprintf(logentry, "Error: SIGTERM could not be send to process # %d!\n", processid);
write_logfile(logentry, LOG_ERROR);
}
} else {
sprintf(logentry, "Error: file with process-ID could not be opened: %s!\n", fullpath_smsfile_PID);
write_logfile(logentry, LOG_ERROR);
}
} // end of if if (stopsignal_flag == STOPSIGNAL_TRUE)
break; // break for case MESSAGE_TYPE_SMS
case MESSAGE_TYPE_MAIL :
if ( stopfile_flag == STOPFILE_TRUE ) {
strcpy(stopfile, configvariables[path_incoming_mail_count]); // we get the path were the incoming SMS will be written in
strcat(stopfile, configvariables[message2action_stop_filename_count]);
sprintf(logentry, "Info: filename for STOP-mail: %s\n", stopfile);
write_logfile(logentry, LOG_INFO);
filep = fopen(stopfile, "w+");
if ( filep != 0 ) {
return_mailaddress_from_inifile(logentry); // we get first valid mailaddress from ini-file
sprintf(From_line, "From: <%s>", logentry);
#ifdef DEVSTAGE
sprintf(logentry, "Info: 1. line in STOP-mail-file: %s\n", From_line);
write_logfile(logentry, LOG_INFO);
#endif
fputs(From_line, filep);
// the following string is constant, none of the values will be read:
sprintf(logentry, "\nSubject: %s", configvariables[message2action_stop_command_count]); // we take the stop-command from the ini-file
fputs(logentry, filep);
#ifdef DEVSTAGE
write_logfile("Info: dummy-line written to STOP-mail-file.\n", LOG_INFO);
#endif
fclose(filep);
write_logfile("Info: STOP-mail-file successfully written and closed.\n", LOG_INFO);
} else { // we could not open file for creating stop-mail-file
sprintf(logentry, "Error: file %s could not be opened for writing STOP-mail-file!\n", stopfile);
write_logfile(logentry, LOG_ERROR);
}
break;
} // end of if (stoppingmethod == STOPFILE_TRUE)
if (stopsignal_flag == STOPSIGNAL_TRUE) {
processidfilep = fopen(fullpath_mailfile_PID, "rb" );
if (processidfilep != NULL) { // we could open the pid-file
fread(&processid, sizeof(processid), 1, processidfilep);
fclose(processidfilep);
sprintf(logentry, "Info: read process-ID: %d\n", processid);
write_logfile(logentry, LOG_INFO);
killreturnvalue = kill(processid, SIGTERM);
if (killreturnvalue == 0) { // we could send signal to process
sprintf(logentry, "Info: SIGTERM was send to process # %d\n", processid);
write_logfile(logentry, LOG_INFO);
} else { // we could not send signal to process
sprintf(logentry, "Error: SIGTERM could not be send to process # %d!\n", processid);
write_logfile(logentry, LOG_ERROR);
}
} else {
sprintf(logentry, "Error: file with process-ID could not be opened: %s!\n", fullpath_mailfile_PID);
write_logfile(logentry, LOG_ERROR);
}
} // end of if if (stopsignal_flag == STOPSIGNAL_TRUE)
case MESSAGE_TYPE_PUSHBULLET : break;
} // end of switch
} else { // we had a problem to read the configfile
return CONFIG_FILE_READ_ERROR;
}
return NOERROR;
} // end of function stop_processing_sms ****************************************************************
int signaltest() {
printf("Wir üben Signale...\n");
read_config_file(config_filename); // we have to read the configfile because we need the paths to some files
if (install_signal_function(SIGINT, check_signal) == 1 ) printf("Fehler beim installieren des Signalhandlers: SIGINT\n");
else printf("Signalhandler wurde installiert.\n");
if (install_signal_function(SIGTERM, check_signal) == 1 ) printf("Fehler beim installieren des Signalhandlers: SIGTERM!\n");
else printf("Signalhandler wurde installiert.\n");
printf("Nun warten wir 30 Sekunden...\b\n");
sleep(30);
return 0;
} // end of signaltest
//*****************************************************************************************************************
// count_commandline_parameters: counts the number of commandlineparameters we have specified
// input: none
// returncodes: # of allowed parameters
//*****************************************************************************************************************
int count_commandline_parameters (void) {
int counter;
for (counter = 0; ; counter++) {
if (cmdline_parameters[counter] == NULL) return counter;
}
} // end of count_commandline_parameters **************************************************************************
//*****************************************************************************************************************
// main: The program starts here
// input: number of argument, the arguments itself
// exitcodes: 0 for normal end; 1 for error
//*****************************************************************************************************************
int main(int argc, char **argv)
{
int cmdlinecounter = 0;
int valid_cmdline_counter = count_commandline_parameters();
int argumentcounter = 0;
printf(version_of_program);
if (argc > 1) { // we have commandline-parameters
// we try to find out which parameters we have. First we go through list with only one 1 parameter:
if (argc == 2) { // we have in total 1 parameter:
if (strcmp(argv[1], "config") == 0) { cmdlinecounter = 1; print_configfile(); }
if (strcmp(argv[1], "?") == 0) { cmdlinecounter = 1; printf("For documentation please see file message2action.txt.\n"); }
if (cmdlinecounter == 0) printf("Error: invalid argument: %s\nCall program without parameters for help\n", argv[1]);
}
if (argc > 2) { // we have more than 2 parameters, now we step through all parameters: We take each parameter given to the program and check if the parameter is one of the allowed ones
for (argumentcounter = 1; argumentcounter < argc; argumentcounter++) {
valid_parameter_found_flag = FALSE;
for (cmdlinecounter = 2; cmdlinecounter < valid_cmdline_counter; cmdlinecounter++) {
if ( (strcmp(argv[argumentcounter], cmdline_parameters[cmdlinecounter]) == 0) || (strncmp(argv[argumentcounter], cmdline_parameters[cmdlinecounter], strlen(cmdline_parameters[cmdlinecounter])) == 0) ) {
#ifdef DEVSTAGE
printf("Parameter found from commandline: %s\n", argv[argumentcounter]);
#endif
valid_parameter_found_flag = TRUE;
switch(cmdlinecounter) {
case stopsignal_counter : stopsignal_flag = STOPSIGNAL_TRUE; cmdlinecounter = valid_cmdline_counter; break;
case stopfile_counter : stopfile_flag = STOPFILE_TRUE; cmdlinecounter = valid_cmdline_counter; break;
case display_yes_counter : display_flag = DISPLAY_TRUE; cmdlinecounter = valid_cmdline_counter; break;
case display_no_counter : display_flag = DISPLAY_FALSE; cmdlinecounter = valid_cmdline_counter; break;
case log_yes_counter : logging_flag = LOGGING_TRUE; cmdlinecounter = valid_cmdline_counter; break;
case log_no_counter : logging_flag = LOGGING_FALSE; cmdlinecounter = valid_cmdline_counter; break;
case outbound_sms_counter : outbound_sms_flag = TRUE; cmdlinecounter = valid_cmdline_counter; break;
case outbound_mail_counter : outbound_mail_flag = TRUE; cmdlinecounter = valid_cmdline_counter; break;
case outbound_pushbullet_counter : outbound_pushbullet_flag = TRUE; cmdlinecounter = valid_cmdline_counter; break;
case inbound_sms_counter : inbound_flag = TRUE; inbound_sms_flag = TRUE; cmdlinecounter = valid_cmdline_counter; break;
case inbound_mail_counter : inbound_flag = TRUE; inbound_mail_flag = TRUE; cmdlinecounter = valid_cmdline_counter; break;
case inbound_pushbullet_counter : inbound_flag = TRUE; inbound_pushbullet_flag = TRUE; cmdlinecounter = valid_cmdline_counter; break;
case inifile_counter : cmdlinecounter = valid_cmdline_counter; break;
default: printf("Error: unknown parameter: %s\n", argv[argumentcounter]);
} // end of switch-loop
} // end of if-clause
} // end of for-loop
if (valid_parameter_found_flag == FALSE) { printf("Error: unknown parameter: %s\n", argv[argumentcounter]); exit(1);}
} // end of for-loop
// now we know which parameters were given to the program. We have to decide now what has to be done:
if (stopsignal_flag + stopfile_flag > 1) { printf("Error: more than 1 stoppingmethod is not allowed!\n"); exit(1); }
if (inbound_sms_flag + inbound_mail_flag + inbound_pushbullet_flag > 1) { printf("Error: more than 1 inbound is not allowed!\n"); exit(1); }
if (inbound_sms_flag + inbound_mail_flag + inbound_pushbullet_flag == 0) { printf("Error: no inbound specified!\n"); exit(1); }
if (outbound_sms_flag + outbound_mail_flag + outbound_pushbullet_flag > 1) { printf("Error: more than 1 outbound is not allowed!\n"); exit(1); }
if (outbound_sms_flag + outbound_mail_flag + outbound_pushbullet_flag == 0) { // no outbound specified; maybe the cause is that we have to stop
if ((stopsignal_flag == TRUE ) || (stopfile_flag == TRUE)) {
stop_processing_message(return_inbound_messagetype());
exit(0);
} else {
printf("Error: no outbound specified!\n");
exit(1);
}
}
// now we start with processing:
start_processing_message(return_inbound_messagetype());
} // end of if (argc > 2)
} else { // we have no commandline-parameters, we print short help and do nothing
printf("No parameters given, these parameters are possible:\n");
printf("? : print a little help on screen.\n");
printf("config : print content of ini-file and do checks on content %s\n", config_filename);
printf("in=<sms|mail> out=<sms|mail> : use as inbound sms or mail and as outbound sms or mail without logging and in quiet-mode.\n");
printf("in=<sms|mail> out=<sms|mail> display=y: use as inbound sms or mail and as outbound sms or mail without logging but display messages and status on monitor.\n");
printf("in=<sms|mail> out=<sms|mail> log=y: use as inbound sms or mail and as outbound sms or mail with logging but in quiet-mode.\n");
printf("in=<sms|mail> out=<sms|mail> display=y log=y: use as inbound sms or mail and as outbound sms or mail with logging display messages and status on monitor.\n");
printf("in=<sms|mail> stopsignal : send a signal to stop program listening on inbound <sms|mail>\n");
printf("in=<sms|mail> stopfile : create a file which contains message to stop program listening on inbound <sms|mail>\n");
}
exit(0);
}
Alles anzeigen
Das gesamte Paket habe ich als tar-Archiv in meiner Magenta Cloud abgespeichert.
Das tar-Archiv enthält auch Beispieldateien für Mails und SMS, mit denen man das Programm testen kann. Dazu ist weder ein Surfstick, SIM-Karte noch der erwähnte Mailaccount erforderlich.
Als weiteren Kanal zum Emfpangen und Senden von Nachrichten an den Pi plane ich Telegram zu integrieren.
Über Feedback und Anregungen zu meinem Programm würde ich mich freuen.