: Da sich viele Teile der Funktionssignatur wiederholen und aus den Makros/Konstanten bestehen, ist es sinnvoll für die DebugLevel LOG_DEBUG, LOG_INFO, LOG_WARNING und LOG_ERR Makros um die Funktionen logLog(), logLogRC(), logLogRC_SQL(), logEntry(), logExit() und logExitRC() zu definieren.
Diese Makros sollen die Parameter logLevel (LOG_DEBUG/LOG_INFO/LOG_WARNING/LOG_ERR), modulName (__FILE__), lineNumber (__LINE__) und functName (__func__) kapseln.
Als Namen für diese Makros könnte man z.B. LOG_LOG_DEBUG()/LOG_LOG_INFO()/LOG_LOG_WARNING()/LOG_LOG_ERR() verwenden.
Logging-Modul - nützliche Log-Funktionen.
logging_ext.h:
/********************************************************************* * * Autor: Jürgen Kreick * Version: 1.0.0 vom 10.09.2010 * ********************************************************************** * * Achtung! Dieses Modul (in der aktuellen Version) ist nicht reenterable! * * Für MultiThreaded Betrieb nur bedingt geeignet! * ********************************************************************** * * Hinweise zum Modul/Quelltext: Keine aktuellen Hinweise. * ********************************************************************** * * Release Notes: * * Ver 1.0.0 (vom 10.09.2010): * Die erste Version des Moduls. Umfasst (nach außen) folgende Funktionen: * logInit(), logDone(), logLog(), logLogRC(), logLogRC_SQL(), * logEntry(), logExit(), logExitRC(), logErrorMsgFatal(). * **********************************************************************/ #ifndef logging_ext_h_H #define logging_ext_h_H // Wegen LogLevel (soll einheitlich zu Syslog bleiben) #include <syslog.h> // Typ "FILE" #include <stdio.h> // Standard-LogLevel: #define LOGLEVEL_STD 5 // Zur Abgrenzung (und Plausibilitätspruefung): der gleiche Wert wie der min./max. LogLevel #define LOGLEVEL_MIN 0 #define LOGLEVEL_MAX 7 // Rückgabewerte: #define RC_OK 0 #define RC_ERR -1 // Status zum LogFile (Extension für den FileNamen) dranhängen #define LOGSTATUS_RUN "RUN" #define LOGSTATUS_CLOSE "CLOSED" // Vordefinierte (ungültige) LogFile-IDs: #define LOGFILE_NOFILE 0 #define LOGFILE_ERROR -2 // Vordefinierte LogFile-Texte: #define LOGTXT_FUNCTION_ENTRY "FUNCTION ENTRY" #define LOGTXT_FUNCTION_EXIT "FUNCTION EXIT" // Datums- und Zeitformat: // Achtung! // Makros LOG_?????_FORMAT_MEM sollen genauen Speicherbedarf (in Zeichen) für // die entsprechenden LOG_?????_FORMAT widerspiegeln! Sie werden für die // Deklaration von String-Buffern genutzt. // Das ist nicht etwa die Länge des LOG_?????_FORMAT-Strings, sondern die Länge // des Strings, der durch das sprintf(LOG_?????_FORMAT, ...) erzeugt wird. // Wird hier ein zu kleiner Wert derfiniert, führt es zum BufferOverflow. // Datum JJJJ-MM-TT #define LOG_DATUM_FORMAT "%04d-%02d-%02d" #define LOG_DATUM_FORMAT_MEM 10 // Zeit SS-MM-ss #define LOG_ZEIT_FORMAT "%02d-%02d-%02d" #define LOG_ZEIT_FORMAT_MEM 8 // ******************** Prototypen **************************************** // logInit() wird ein Mal pro LogFile aufgerufen und legt dabei das LogFile an. // (Beim allerersten Aufruf wird zusätzlich das gesamte Log-Modul initialisiert.) // // Parameter: // // Es gibt 2 Varianten des Aufrufs: // // 1) Die logInit() generiert den FileNamen des LogFiles automatisch aus dem // Namen des Programms (char *progName), des aktuellen Datums und der // aktuellen Uhrzeit und legt es im angegebenen Ordner (char *loggingPath) // an. Der Parameter "char *logPathFileName" soll dabei NULL bleiben. // // 2) Die logInit() übernimmt den FileNamen des LogFiles samt Pfad aus dem // Parameter "char *logPathFileName" und fügt lediglich die Endung // beispielsweise ".RUN" bzw. ".CLOSED" hinzu. // // In beiden Fällen wird die Endung über den Parameter "char *extRun" und // "char *extClosed" bestimmt. // // char *loggingPath : Verzeichnis, in dem das LogFile angelegt werden soll // char *progName : Anfang des Dateinamens // char *logPathFileName : Entweder NULL (Kein konkretes File), // oder kompletter (mit Pfad) FileName // char *extRun : Entweder NULL (Keine Erweiterung des FileNamens), // oder eine Erweiterung, z.B. "RUN". // Diese wird am Ende des FileNamens angehängt. // char *extClosed : Entweder NULL (Keine Erweiterung des FileNamens), // oder eine Erweiterung, z.B. "CLOSED". // Diese bekommt das File nachdem die logDone(logFileID) // aufgerufen wird (normalerweise beim Programmende). // int threadNum : Falls mehrere Thread in separate LogFiles schreiben sollen, // hier die Thread-Nummer, sonst 0 // int logLevelMax : Bis zu welchem LogLevel die Ausgabe erfolgen soll. (Alle // niedrigeren LogLevel werden mitgeloggt.) // Dateiname wird nach dem Schema "progName.JJJJ-MM-TT.SS-MM-ss.PID.ThreadNr.log.Status" gebildet. // // Rückgabewert: die "int logFileID" - sie wird bei allen Logging Funktionen // (innerhalb dieses Moduls) als Bezug auf das konkrete LogFile verwendet. // Bei Fehlern wird LOGFILE_ERROR als Rückgabewert zurück gegeben. int logInit (const char *loggingPath, const char *progName, const char *logPathFileName, const char *extRun, const char *extClosed, int threadNum, int logLevelMax); // logDone() schließt das über die logFileID referenziertes LogFile und ändert // dessen Status (den letzten Teil des Namen von ".RUN" auf ".CLOSED"). // Mit dem Parameter 0 aufgerufen schließt sie alle LogFiles. void logDone (int logFileID); // Allgemeine Logging-Funktion. // // Parameter: // int logLevel : Unter welchem LogLevel soll die Ausgabe erfolgen. Falls // "logLevel" den "logLevelMax" beim Aufruf von logInit() // überschreitet, erfolgt keine Ausgabe. // int logFileID : Die LogFile-Referenz - das Ergebniss von logInit() // char *modulName : Modul-Name, das die Ausgabe produziert. In meisten Fällen // wird als Makro __FILE__ übergeben. // int lineNumber : Zeilennummer, die die Ausgabe produziert. In meisten Fällen // wird als Makro __LINE__ übergeben. // char *functName : Name der Funktion, die die Ausgabe produziert. In meisten // Fällen wird als Makro __func__ übergeben. // char *text : Die eigentliche Log-Ausgabe. // // Rückgabewert: Erfolg (Ausgabe erfolgreich) / Misserfolg (Ausgabe nicht erfolgrei oder LogLevel zu niedrig). int logLog (int logLevel, int logFileID, const char *modulName, int lineNumber, const char *functName, const char *text); // // Das gleiche wie oben, nur mit Angabe von RC (ReturnCode) // // Parameter: wie oben, jedoch ein Parameter zusätzlich: // int rc : ReturnCode, wird hinter dem "text" ausgegeben. int logLogRC (int logLevel, int logFileID, const char *modulName, int lineNumber, const char *functName, const char *text, int rc); // // Das gleiche wie oben, nur für SQL // // Diese Funktion kann nach jeder DB-Operation aufgerufen werden // (insbesondere falls der SQL-Code nicht RC_DB_OK ist). // // Parameter: wie oben, jedoch ein Parameter zusätzlich: // const char *sql : Der SQL selbst. int logLogRC_SQL (int logLevel, int logFileID, const char *modulName, int lineNumber, const char *functName, const char *text, const char *sql, int rc_SQL); // Logging-Funktionen zum Markieren der Ein- und Ausstiegsstelle in den Funktionen. // // Parameter: wie oben. int logEntry (int logLevel, int logFileID, const char *modulName, const char *functName); int logExit (int logLevel, int logFileID, const char *modulName, const char *functName); // ...und für Exit mit ReturnCode int logExitRC (int logLevel, int logFileID, const char *modulName, const char *functName, int rc); // Bei Fatalfehler wird eine Fehlermeldung auf "stderr" ausgegeben und die gesamte Anwendung mit exit(exitCode) unterbrochen. // // Parameter: wie oben. void logErrorMsgFatal (int exitCode, const char *modulName, int lineNumber, const char *functName, const char * fehlermeldung); /* Everything else goes here */ #endif // EOF
logging_ext.c:
#include "logging_ext.h" // Makro ASSERT() #include <sys/debug.h> // Zeit-Funktionen und Strukturen #include <time.h> // Wegen der Funktion "max(int int1, int int2)": #include <sys/ddi.h> //////////////////////////////////////////////////////////////////////////////// // // Zur Info: LogLevel aus syslog.h // LOG_EMERG 0 /* system is unusable */ // LOG_ALERT 1 /* action must be taken immediately */ // LOG_CRIT 2 /* critical conditions */ // LOG_ERR 3 /* error conditions */ // LOG_WARNING 4 /* warning conditions */ // LOG_NOTICE 5 /* normal but signification condition */ // LOG_INFO 6 /* informational */ // LOG_DEBUG 7 /* debug-level messages */ // //////////////////////////////////////////////////////////////////////////////// // LogLevel als String für die Ausgabe im LogFile: #define LOG_STR_EMERG "EMERGENCY" #define LOG_STR_ALERT "ALERT" #define LOG_STR_CRIT "CRITICAL" #define LOG_STR_ERR "ERROR" #define LOG_STR_WARNING "WARNING" #define LOG_STR_NOTICE "NOTICE" #define LOG_STR_INFO "INFO" #define LOG_STR_DEBUG "DEBUG" // Restliche Konstanten: #define TMP_STR_LEN_MAX 8191 #define FILENAME_LEN_MAX 8191 // So viele LogFiles parallel kann dieses Modul verwalten #define AKTIVE_LOGFILES_MAX 64 // Status #define LOGFILE_AKTIVE 1 #define LOGFILE_FREE 0 // Ausgabeformat in der Funktion logLogRC() #define LOG_RC_FORMAT "%s (RC = %d)" // Ausgabeformat in der Funktion logExitRC() #define LOG_EXIT_RC_FORMAT "%s (RC = %d)" // Ausgabeformat in der Funktion logLogRC_SQL() #define LOG_RC_SQL_FORMAT "SQL: '%s;' %s (SQL-CODE = %d)" // Vordefinierte LogFile-Meldungen: #define LOGTXT_TEXT_TOO_LONG "Log-Ausgabe ist zu lang" // ******************** lokale Strukturen **************************************** // Steuerstruktur für alle LogFiles typedef struct { int id; // logische Nummer eines Log-Files int active; // 1 = aktiv, 0 = frei int logLevel; // bis zu welchem LogLevel loggen int thread; // falls mehrere Thread aktiv sind, Thread-Nummer, sonst 0 FILE *logFile; // FileDescriptor char fileNameRun [FILENAME_LEN_MAX + 1]; // FileName im aktiven Zustand (mit .RUN am Ende) char fileNameClose [FILENAME_LEN_MAX + 1]; // FileName im inaktiven Zustand (mit .CLOSED am Ende) } LOGFILE_CONTROL; // ******************** lokale Variablen **************************************** // Zähler für momentan aktive LogFiles. // Solange die "initLogFileCtl(0)" nicht aufgerufen wurde (anfängliche Initialisierung), // bleibt "countAktiveLogFiles" im Fehlerzustand und hindert jegliche weitere Funktion // des Moduls. int countAktiveLogFiles = LOGFILE_ERROR; int myPID = -1; // eigene Prozess-ID (Bestandteil des Namens des LogFiles) int threaded = 0; // Soviele Ausgaben erfolgen in den Threads (parallel). LOGFILE_CONTROL logFileCtl [AKTIVE_LOGFILES_MAX + 1]; // Steuerstrukturen für alle LogFiles (Element 0 unbenutzt) char *logLevel2String [] = { LOG_STR_EMERG, // 0 "EMERGENCY" LOG_STR_ALERT, // 1 "ALERT" LOG_STR_CRIT, // 2 "CRITICAL" LOG_STR_ERR, // 3 "ERROR" LOG_STR_WARNING, // 4 "WARNING" LOG_STR_NOTICE, // 5 "NOTICE" LOG_STR_INFO, // 6 "INFO" LOG_STR_DEBUG // 7 "DEBUG" }; // ******************** interne Funktionen **************************************** void initLogFileCtl (int id) // initialisiert eine logFileCtl[id], falls id = 0 - gesamte Struktur { // Die ID darf nur zwischen 0 und AKTIVE_LOGFILES_MAX bewegen (beide einschließlich) ASSERT((id >= 0) && (id <= AKTIVE_LOGFILES_MAX)); if (id == 0) // Gesamte Struktur initialisieren { // Diese Initialisierung findet nur ein Mal statt - beim Start der Anwendung ASSERT(countAktiveLogFiles == LOGFILE_ERROR); // Die Struktur darf noch nicht initialisiert sein memset(&logFileCtl, 0x00, sizeof(logFileCtl)); countAktiveLogFiles = 0; threaded = 0; myPID = getpid(); // eigene Prozess-ID } else // Eine einzelne Komponente initialisieren { ASSERT(countAktiveLogFiles >= 0); // Die Struktur muss bereits initialisiert sein memset(&(logFileCtl[id]), 0x00, sizeof(logFileCtl[0])); // nur eine logFileCtl[id] initialisieren } // if } // initLogFileCtl() int getNewLogFileCtl () { int rc = LOGFILE_ERROR; register int i; for (i = 1; i <= AKTIVE_LOGFILES_MAX; i++) // durch die ganze Tabelle { if (!(logFileCtl[i].active)) // Noch nicht aktiv? { rc = i; // ID merken break; // Keine weitere Suche } // if } // for if ((rc <= 0) || (rc > AKTIVE_LOGFILES_MAX)) rc = LOGFILE_ERROR; if (rc > 0) initLogFileCtl(rc); // ID initialisieren return rc; // ID zurueck, oder -2 (LOGFILE_ERROR) wenn nichts passendes gefunden } // getNewLogFileCtl() void getCurrentDateAndTime (char *currentDate, const char *formatDate, char *currentTime, const char *formatTime) { // ----- Achtung! Mehrere returns innerhalb der Funktion ------------------------------ time_t aktSekunden; struct tm *aktZeit; if (!currentDate) return; if (!formatDate) return; if (!currentTime) return; if (!formatTime) return; time(&aktSekunden); // aktuelle Zeit holen aktZeit = localtime(&aktSekunden); // auf Komponenten zerlegen // Achtung! sprintf() ist unsicher! // Es findet hier keine Prüfung statt, ob in "currentTime" und "currentDate" genug Platz vorhanden ist! sprintf(currentTime, formatTime, aktZeit->tm_hour, aktZeit->tm_min, aktZeit->tm_sec); // Uhrzeit sprintf(currentDate, formatDate, aktZeit->tm_year + 1900, aktZeit->tm_mon + 1, aktZeit->tm_mday); // Datum } // getCurrentDateAndTime() // Diese Funktion berechnet wieviele Stellen (samt '-' bei negativen) eine Ganzzahl im String-Format belegt. int intlen (int zahl) { int len = 0; // Initialisierungswert if (zahl < 1) len = 1; // Bei 0 wird nicht gezählt, bei negativen eine Stelle dazu wegen Vorzeichen. else len = 0; zahl = abs(zahl); while (zahl > 0) { zahl = zahl / 10; // Um eine Stelle kürzen len++; // Eine Stelle dazu zählen } // while return len; } // intlen() // ******************** export-Funktionen **************************************** int logInit (const char *loggingPath, const char *progName, const char *logPathFileName, const char *extRun, const char *extClosed, int threadNum, int logLevelMax) { int rc = RC_OK; int logFileID = LOGFILE_ERROR; FILE *logFile = NULL; char fileName [FILENAME_LEN_MAX + 1]; char strZeit [LOG_ZEIT_FORMAT_MEM + 1]; char strDatum [LOG_DATUM_FORMAT_MEM + 1]; int logFileNameReserve = 0; memset(fileName, '\0', sizeof(fileName)); memset(strZeit, '\0', sizeof(strZeit)); memset(strDatum, '\0', sizeof(strDatum)); if (countAktiveLogFiles == LOGFILE_ERROR) initLogFileCtl(0); // D.h. nur beim ersten Aufruf initialisieren. if ((logFileID = getNewLogFileCtl()) > 0) rc = RC_OK; // wenn eine neue ID erteilt wurde else rc = RC_ERR; // keine neue ID verfügbar if (!rc) { if (logLevelMax < LOGLEVEL_MIN) logLevelMax = LOGLEVEL_MIN; if (logLevelMax > LOGLEVEL_MAX) logLevelMax = LOGLEVEL_MAX; logFileCtl[logFileID].id = logFileID; // Struktur ausfüllen if (logPathFileName) // Falls ein konkreter FileName vorgegeben wurde, diesen als Basis verwenden. { // Die Verlängerung des FileNamens (logFileNameReserve) berechnen. if (extRun && extClosed) logFileNameReserve = max(strlen(extRun), strlen(extClosed)) + 1; // 1 für das '.'-Zeichen else if (extRun) logFileNameReserve = strlen(extRun) + 1; else if (extClosed) logFileNameReserve = strlen(extClosed) + 1; else logFileNameReserve = 0; // Keine Endungen strlcpy(fileName, logPathFileName, sizeof(fileName) - logFileNameReserve); // Den FileNamen übernehmen } else // Den FileNamen selbstständig generieren. { getCurrentDateAndTime(strDatum, LOG_DATUM_FORMAT, strZeit, LOG_ZEIT_FORMAT); snprintf(fileName, sizeof(fileName), "%s/%s.%s.%s.%d.%d.log", loggingPath, progName, strDatum, strZeit, myPID, threadNum); // StammName } // if // Den kompletten FileNamen bilden - für den RUN-Zustand. if (extRun) snprintf(logFileCtl[logFileID].fileNameRun, sizeof(logFileCtl[0].fileNameRun), "%s.%s", fileName, extRun); else strlcpy(logFileCtl[logFileID].fileNameRun, fileName, sizeof(logFileCtl[0].fileNameRun)); // Den kompletten FileNamen bilden - für den CLOSED-Zustand. if (extClosed) snprintf(logFileCtl[logFileID].fileNameClose, sizeof(logFileCtl[0].fileNameClose), "%s.%s", fileName, extClosed); else strlcpy(logFileCtl[logFileID].fileNameClose, fileName, sizeof(logFileCtl[0].fileNameClose)); logFile = fopen(logFileCtl[logFileID].fileNameRun, "w"); // zum Schreiben öffnen if (logFile) { if (setvbuf(logFile, NULL, _IOLBF, TMP_STR_LEN_MAX + 1) != 0) // Zeilenbuffer anlegen { fclose(logFile); // Bei mißerfolg. logFile = NULL; } // if } // if if (logFile) logFileCtl[logFileID].logFile = logFile; // Falls geöffnet, den FileHandle zuweisen... else logFileCtl[logFileID].logFile = stderr; // ...sonst "stderr"-Handle logFileCtl[logFileID].logLevel = logLevelMax; // Den "persönlichen" LogLevel merken. logFileCtl[logFileID].thread = threadNum; // Thread-Nummer merken. if (logFile) logFileCtl[logFileID].active = LOGFILE_AKTIVE; // auf aktiv setzen else rc = RC_ERR; if (logFileCtl[logFileID].active == LOGFILE_AKTIVE) // Falls ein aktives LogFile dazu gekommen... { countAktiveLogFiles++; // ... eins dazu zählen. if (logFileCtl[logFileID].thread > 0) threaded++; // Es ist also mit paralleler Ausgabe zu rechnen. } // if } // if if (!rc) rc = logFileID; else rc = LOGFILE_ERROR; return rc; // LogFile-ID } // logInit() void logDone (int logFileID) { // ----- Achtung! Mehrere returns innerhalb der Funktion ------------------------------ if (logFileID == 0) { int i; for (i = 1; i <= AKTIVE_LOGFILES_MAX; i++) logDone(i); // Alle LogFiles schließen return; } // if if ((logFileID < 1) || (logFileID > AKTIVE_LOGFILES_MAX)) return; // ID ist nicht plausibel if (logFileCtl[logFileID].active != LOGFILE_AKTIVE) return; // ID ist nicht aktiv // Ab hier Files schließen und die ID deaktivieren. if (logFileCtl[logFileID].logFile) fflush(logFileCtl[logFileID].logFile); if (logFileCtl[logFileID].logFile == stderr) logFileCtl[logFileID].logFile = NULL; // Bei "stderr" keine weiteren Aktivitäten. if (logFileCtl[logFileID].logFile) fclose(logFileCtl[logFileID].logFile); logFileCtl[logFileID].logFile = NULL; // Wechsel vom RUN- zum CLOSED-Zustand. rename(logFileCtl[logFileID].fileNameRun, logFileCtl[logFileID].fileNameClose); // Log-File umbenennen logFileCtl[logFileID].active = LOGFILE_FREE; // nicht mehr aktiv if (logFileCtl[logFileID].thread) threaded--; // Um einen Thread weniger. if (threaded < 0) threaded = 0; // Darf nicht negativ sein (dürfte eigentlich nicht vorkommen). logFileCtl[logFileID].thread = 0; countAktiveLogFiles--; if (countAktiveLogFiles < 0) countAktiveLogFiles = 0; // Darf nicht negativ sein (dürfte eigentlich nicht vorkommen). } // logDone() int logLog (int logLevel, int logFileID, const char *modulName, int lineNumber, const char *functName, const char *text) { int rc = RC_OK; int logFileIdLogLevel = 0; char strZeit [LOG_ZEIT_FORMAT_MEM + 1]; char strDatum [LOG_DATUM_FORMAT_MEM + 1]; memset(strZeit, '\0', sizeof(strZeit)); memset(strDatum, '\0', sizeof(strDatum)); // Ist die logFileID plausibel? if ((logFileID < 1) || (logFileID > AKTIVE_LOGFILES_MAX)) rc = RC_ERR; // ID ist nicht plausibel if ((logLevel < LOGLEVEL_MIN) || (logLevel > LOGLEVEL_MAX)) rc = RC_ERR; // LogLevel ist nicht plausibel if (rc) logFileID = 0; // damit durch fehlerhafte logFileID kein Segmentation Fault ausgelöst wird // ist die logFileID aktiv? if (!rc) if (logFileCtl[logFileID].active != LOGFILE_AKTIVE) rc = RC_ERR; // ID ist nicht plausibel logFileIdLogLevel = logFileCtl[logFileID].logLevel; if (!rc && (logLevel <= logFileIdLogLevel)) // Ausgabe in LogFile nur wenn der LogLevel passt. { getCurrentDateAndTime(strDatum, LOG_DATUM_FORMAT, strZeit, LOG_ZEIT_FORMAT); // Die Ausgabe ins LogFile abhängig vom zur logFileID gehörenden logLevel schreiben: // Log-Ausgabe für logEntry() / logExit() / logExitRC() (mit "modulName" und "functName") if (lineNumber == -1) fprintf(logFileCtl[logFileID].logFile, "%s %s %s: %s:%s(): %s\n", strDatum, strZeit, logLevel2String[logLevel], modulName ? modulName : "NOMODUL(NULL-POINTER)", functName ? functName : "NOFUNKT(NULL-POINTER)", text ? text : "NOTEXT(NULL-POINTER)"); // Log-Ausgabe für logLevel = LOG_DEBUG (und evtl. höher) erfolgt mit "modulName", "lineNumber", und "functName" (alle Angaben) else if (logFileIdLogLevel >= LOG_DEBUG) fprintf(logFileCtl[logFileID].logFile, "%s %s %s: %s[%d]:%s(): %s\n", strDatum, strZeit, logLevel2String[logLevel], modulName ? modulName : "NOMODUL(NULL-POINTER)", lineNumber, functName ? functName : "NOFUNKT(NULL-POINTER)", text ? text : "NOTEXT(NULL-POINTER)"); // Log-Ausgabe für logLevel = LOG_INFO (und evtl. höher) erfolgt nur mit "functName" else if (logFileIdLogLevel >= LOG_INFO) fprintf(logFileCtl[logFileID].logFile, "%s %s %s: %s(): %s\n", strDatum, strZeit, logLevel2String[logLevel], functName ? functName : "NOFUNKT(NULL-POINTER)", text ? text : "NOTEXT(NULL-POINTER)"); // allgemeine Log-Ausgabe (nur mit Zeitstempel) else fprintf(logFileCtl[logFileID].logFile, "%s %s %s: %s\n", strDatum, strZeit, logLevel2String[logLevel], text ? text : "NOTEXT(NULL-POINTER)"); if (threaded) fflush(logFileCtl[logFileID].logFile); // Bei mehreren Threads sofort wegschreiben. } // if return rc; } // logLog() int logLogRC (int logLevel, int logFileID, const char *modulName, int lineNumber, const char *functName, const char *text, int rc) { char logStr [TMP_STR_LEN_MAX + 1]; memset(logStr, '\0', sizeof(logStr)); if ((strlen(text) + intlen(rc) + strlen(LOG_RC_FORMAT)) > TMP_STR_LEN_MAX) strcpy(logStr, LOGTXT_TEXT_TOO_LONG); // Ausgabe-String zu lang. else sprintf(logStr, LOG_RC_FORMAT, text, rc); // Achtung! sprintf() ist unsicher! return logLog(logLevel, logFileID, modulName, lineNumber, functName, logStr); } // logLogRC() int logLogRC_SQL (int logLevel, int logFileID, const char *modulName, int lineNumber, const char *functName, const char *text, const char *sql, int rc_SQL) { char logStr [TMP_STR_LEN_MAX + 1]; memset(logStr, '\0', sizeof(logStr)); if ((strlen(sql) + strlen(text) + intlen(rc_SQL) + strlen(LOG_RC_SQL_FORMAT)) > TMP_STR_LEN_MAX) strcpy(logStr, LOGTXT_TEXT_TOO_LONG); // Ausgabe-String zu lang. else sprintf(logStr, LOG_RC_SQL_FORMAT, sql, text, rc_SQL); // Achtung! sprintf() ist unsicher! return logLog(logLevel, logFileID, modulName, lineNumber, functName, logStr); } // logLogRC_SQL() int logEntry (int logLevel, int logFileID, const char *modulName, const char *functName) { return logLog(logLevel, logFileID, modulName, -1, functName, LOGTXT_FUNCTION_ENTRY); } // logEntry() int logExit (int logLevel, int logFileID, const char *modulName, const char *functName) { return logLog(logLevel, logFileID, modulName, -1, functName, LOGTXT_FUNCTION_EXIT); } // logExit() int logExitRC (int logLevel, int logFileID, const char *modulName, const char *functName, int rc) { char logStr [TMP_STR_LEN_MAX + 1]; memset(logStr, '\0', sizeof(logStr)); sprintf(logStr, LOG_EXIT_RC_FORMAT, LOGTXT_FUNCTION_EXIT, rc); // Achtung! sprintf() ist unsicher! // Unbedingt darauf achten, daß "logStr" für die Ausgabe groß genug ist! return logLog(logLevel, logFileID, modulName, -1, functName, logStr); } // logExitRC() void logErrorMsgFatal (int exitCode, const char *modulName, int lineNumber, const char *functName, const char * fehlermeldung) { fprintf(stderr, "\n%%s[%d]:%s(): FATAL ERROR: [%s]\n", modulName ? modulName : "NOMODUL(NULL-POINTER)", lineNumber, functName ? functName : "NOFUNKT(NULL-POINTER)", fehlermeldung ? fehlermeldung : "(undefinierte Fehlermeldung)"); fprintf(stderr, "Die Ausfuehrung wird mit ExitCode = [%d] abgebrochen.\n\n", exitCode); fflush(stderr); fflush(stdout); exit(exitCode); } // errorMsgFatal() // EOF
Stand: 10.09.2010
— : Jürgen Kreick
EOF