void CJsonRPC::JsonError( const char* err, bool p_bCallTop/*=false*/ ) { struct json_object *rsp_obj = json_object_new_object () ; json_object_object_add(rsp_obj, "error", json_object_new_string(err) ) ; JsonError(rsp_obj,p_bCallTop); json_object_put(rsp_obj); log2flash("JsonError: %s", err); }
int fclose_s(FILE *fp) { int rv = fclose(fp) ; if ( EOF == rv ) { LOG_ERR("fclose failed"); log2flash("CGI: fclose failed:[%s]", strerror(errno) ) ; } return rv ; }
int fputc_s(int c, FILE *stream) { int rv = fputc (c, stream) ; if ( EOF == rv ) { ERR("Unable to fputc(%02X) in tmpfile: %s", c, strerror(errno)); log2flash("CGI: ERROR: Unable to fputc(%02X) in tmpfile: %s", c, strerror(errno)); } return rv ; }
////////////////////////////////////////////////////////////////////////////////// // Description : read a message from the pipe // Parameters : // char * p_pHeader - output - the header // int m_nHeaderSize - input - the expected header size // char ** p_ppData - output - the data - it not must be deallocated outside // int * p_pDataLen - output - the data length // Return : // 0 on error or 1 on success ////////////////////////////////////////////////////////////////////////////////// int CPipe::ReadMsg( void * p_pHeader, int m_nHeaderSize, const char ** p_ppData, int * p_nDataLen ) { // LOG( "CPipe::readMsg reading header %d", m_nHeaderSize); // lock(); if (!readStartMarker()) { //unlock(); return 0; } if( ! readBlock( (char*)p_pHeader, m_nHeaderSize ) ) { LOG_ERR( "CPipe::ReadMsg: could not read header from pipe"); //unlock(); return 0; } char * p; int nDataLen = 0; memcpy( &nDataLen, p_pHeader, sizeof(nDataLen) ); nDataLen -= (m_nHeaderSize-4); //LOG( "CPipe::readMsg header ok. datalen %d", nDataLen); if(IsSysMemoryLow(nDataLen/1024) ) { log2flash("ERR (CPipe::ReadMsg): MEMORY LOW %dkB (req %d kB)", GetSysFreeMemK(), nDataLen/1024); return 0; } if( ( p = (char *) realloc( m_pBuffer, nDataLen ) ) == NULL && nDataLen ) { LOG_ERR( "CPipe::ReadMsg: cannot realloc %d bytes, pipe corrupted", nDataLen ); //unlock(); return 0; } m_pBuffer = p; if( nDataLen && !readBlock( m_pBuffer, nDataLen ) ) { LOG_ERR( "CPipe::ReadMsg: could not read data section, pipe corrupted"); //unlock(); return 0; } // unlock(); *p_ppData = m_pBuffer; *p_nDataLen = nDataLen; return 1; }
/// This is the main() function of the application. It simply runs the CModuleNameApp object int main(int argc, char *argv[]) { if (argc >1 && strcmp( argv[1], "-v") == 0 ) { LOG( "Version %s", CApp::GetVersion() ); return 0; } CSignalsMgr::Ignore( SIGUSR2 ); ///< Ignore until we install the real handler log2flash("EntryPoint Start: version %s", CApp::GetVersion() ); if( g_pApp->Init() ) { try { ///tests CEPTestCases tests(*g_pApp); tests.RunTests(); g_pApp->Run(); //entering normal operation loop g_pApp->Close(); } catch( std::bad_alloc &ba ) { g_stLog.EmergencyMsg("FATAL ERROR Gateway: catch std::bad_alloc. Probably OUT OF MEMORY"); } catch(...) { g_stLog.EmergencyMsg("FATAL ERROR Gateway: catch(...)"); } log2flash("EntryPoint end"); delete g_pApp; return 0; } log2flash("EntryPoint end <- Init failed"); delete g_pApp; return 1; }
void CJsonRPC::logModifiers( int met_id, char * str ) { switch ( met_id ) { #if defined (RELEASE_ISA) || defined (RELEASE_WHART) || defined (RELEASE_MCSAPP) case ISA100_SM_SETDEVICE: case ISA100_SM_DELDEVICE: //ISA100_MODBUS_GW_DELROW //ISA100_MH_SETPUBLISHER //ISA100_MODBUS_SERVER_SETROW, //ISA100_MODBUS_GW_SETROW, //ISA100_MH_DELPUBLISHER, //ISA100_MODBUS_SERVER_DELROW #endif #ifdef RELEASE_EL case DEVICE_REMOVE: case DEVICE_UPDATE: case DEVICE_STARTTEST: case REPORT_SETREPORTSCHEDULE: case MISC_SETGATEWAY: case MISC_SETPROFILE: #endif #ifndef CORE_NOT_AVAILABLE case MISC_APPLYCONFIGCHANGES: case MISC_HARDRESET: case MISC_SOFTWARERESET: case MISC_RESTARTAPP: //MISC_FILEDOWNLOAD //MISC_FILEUPLOAD //MISC_REMOTECMD //MISC_SETGATEWAYNETWORKINFO case CONFIG_SETVARIABLE: case CONFIG_SETGROUPVARIABLES: #endif FLOG("CGI: %s", str); log2flash( "CGI: %s", str); break ; default: break; } }
bool CDiscoveryApp::update_rcnetinfo(const char *file_name, in_addr_t ip, in_addr_t mask, in_addr_t gw, const struct sockaddr_in& p_stClientAddr, const char *comment/* ="#AUTOMATICALLY GENERATED." */) { char ethInterf_ip[100]={0}; char ethInterf_mask[100]={0}; char ethInterf_gw[100]={0}; in_addr sip = {ip}, smask={mask}, sgw={gw}; strcpy(ethInterf_ip, inet_ntoa(sip)); strcpy(ethInterf_mask, inet_ntoa(smask)); strcpy(ethInterf_gw, inet_ntoa(sgw)); log2flash( "DISCOVERY: Set %s [IP %s/Mask %s/GW %s] from %s", m_szEthInterf, ethInterf_ip, ethInterf_mask, ethInterf_gw, inet_ntoa( p_stClientAddr.sin_addr ) ); if (!file_name) { LOG("NULL file_name"); return false; } FILE *f; if ((f=fopen(file_name,"w+"))==NULL) { LOG("Error fopen: %s", strerror(errno)); fclose(f); return false; } if (fprintf(f,"%s\nETH0_IP=%s\nETH0_MASK=%s\nETH0_GW=%s\nETH_NAME=%s\n", comment, ethInterf_ip, ethInterf_mask,ethInterf_gw, m_szEthInterf)<0) { LOG("Error on fprintf :%s", strerror(errno)); fclose(f); return false; } fclose(f); return true; }
static bool log2flash_fa(const char *fname, const char *fmt, va_list arglist) { bool retcode=false; // assume operation failed. int fd; time_t cur_time; time_t duration=0; struct tm *ptm; // structure to obtain date information char printbuf[MAX_WRITE_CHAR+2]; // size + '\n' + '\0' int bytes_to_write; int lock_to; // time out for flock() DPRINT( "log2flash_fa() called\n" ); fd = open(fname, O_RDWR|O_CREAT|O_NONBLOCK, 00644); if (fd == -1) { LOG_ERR("log2flash ERROR: Unable to open file."); goto EXIT; } lock_to = FLOCK_TIMEOUT; while( flock(fd, LOCK_EX | LOCK_NB) != 0 ) { sleep(1); lock_to--; if (lock_to < 0) { LOG_ERR("log2flash ERROR: lock timeout"); goto CLOSE_EXIT; } } if ( lseek(fd, 0, SEEK_END) == -1 ) { LOG_ERR("log2flash ERROR: unable to seek to the end of file. errno=%d", errno); goto CLOSE_EXIT; } cur_time=time(NULL); ptm=gmtime(&cur_time); // tm_year from 1900, tm_mon [0-11] // it takes 20 characters spaces. sprintf(printbuf, "%d-%02d-%02d %02d:%02d:%02d ", ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); // generate the buffer string. vsnprintf(printbuf+20, MAX_WRITE_CHAR-20, fmt, arglist); bytes_to_write = strlen(printbuf); printbuf[bytes_to_write] = '\n'; printbuf[++bytes_to_write] = 0; DPRINT( printbuf ); // gather statistic struct stat f_stat; if ( fstat(fd, &f_stat) == -1 ) { LOG_ERR("log2flash ERROR: unable to gatter statistic for %s. errno=%d", fname, errno); goto CLOSE_EXIT; } // if write failed, goto CLOSE_EXIT if (loop_write(fd, printbuf, bytes_to_write) != true) goto CLOSE_EXIT; if ( f_stat.st_size + strlen(printbuf) > LOG_LIMIT) { // starting to rotate DPRINT( "File Size exceeded LOG_LIMIT - Perform rotation\n" ); char from[PATH_MAX]; char to[PATH_MAX]; for( int i=ROTATE_MAX; i>0; --i) { sprintf( from, "%s.%d", fname, i-1); sprintf( to, "%s.%d", fname, i); rename( from, to); } duration = time(NULL); Copy( fname, from, LOG_LIMIT ); unlink( fname ); duration -= time(NULL); if (FileIsExecutable(FTP_SCRIPT)) { char sBaseFile[PATH_MAX]; char sFileName[PATH_MAX]; sprintf(sBaseFile,NIVIS_TMP"activity.log"); AttachDatetime(sBaseFile,sFileName); Copy(from,sFileName); systemf_to(5, FTP_SCRIPT" %s &", sFileName); } } retcode=true; CLOSE_EXIT: flock(fd, LOCK_UN); close(fd); if (duration < -10) { //it really is negative :) we only convert it when we need to show it, below log2flash("Logfile rotation took quite long: %d seconds", -duration); } EXIT: return retcode; }
//retcode: true if DISCOVERY_REPLY must be sent back //retcode false if no reply is necessary either because the incomming //message is wrong or because it must be ignored bool CDiscoveryApp::processData(unsigned char *p, const struct sockaddr_in& p_stClientAddr) { if (p==NULL) { LOG("ERROR processData: parameter NULL"); return false; } if (*(unsigned char *)p!=1) { LOG("ERROR processData: incorrect MessageVersion %d", *(unsigned char *)p); return false; } unsigned char *uchMesssageType=p+sizeof(unsigned char); switch (*uchMesssageType) { case DISCOVERY_QRY: { LOG("DISCOVERY_QRY"); return fillDiscoveryResponse(); // instruct caller to send the reply back } case DISCOVERY_SET: { IPSet_Msg * pIPSet = (IPSet_Msg*)p; LOG("DISCOVERY_SET version %u ANID %u (x%X)", pIPSet->m_uchMessageVersion, ntohl(pIPSet->m_unAnId), ntohl(pIPSet->m_unAnId) ); unsigned short crc=computeCRC((uint8_t *)pIPSet, (uint16_t)(sizeof(IPSet_Msg)-sizeof(pIPSet->m_ushCRC))); if (crc!=pIPSet->m_ushCRC) { LOG("ERROR processData: Wrong CRC in ipSet"); return false; } if( ( pIPSet->m_unIP_ethInterf==0x0 ) || ( pIPSet->m_unDefaultGateway==0x0) || ((pIPSet->m_unMask_ethInterf & pIPSet->m_unDefaultGateway) != ( pIPSet->m_unMask_ethInterf & pIPSet->m_unIP_ethInterf)) ) { LOG("ERROR processData: invalid DISCOVERY_SET (IP/GW are zero or IP&mask != GW&mask)"); log2flash( "ERR DISCOVERY: Invalid SET %s [IP %s/Mask %s/GW %s] from %s", m_szEthInterf, pIPSet->m_unIP_ethInterf, pIPSet->m_unMask_ethInterf, pIPSet->m_unDefaultGateway, inet_ntoa( p_stClientAddr.sin_addr )); return false; } IP_array ip_array; //read ip/mask/gw to match with packet if (GetNetworkConfiguration(ip_array) < 0) { return false; } MatchIP_dev( ip_array ); //both ANID/MAC should either match or mismatch. if( matchMAC( pIPSet ) && (!matchANID( pIPSet )) ) { LOG("ERROR processData: MAC match while ANID mismatch (in %u own %u)", ntohl(pIPSet->m_unAnId), ntohl(getANId()) ); } if( (!matchMAC( pIPSet )) && matchANID( pIPSet ) ) { LOG_HEX( "ERROR processData: MAC mismatch while ANID match. In: ", pIPSet->m_uchMAC_Address, sizeof(pIPSet->m_uchMAC_Address) ); LOG_HEX( "ERROR processData: MAC mismatch while ANID match. Own:", m_ucEthInterfMAC, sizeof(m_ucEthInterfMAC) ); } // Compare own MAC and ANID with the ones from the incoming packet if( !( matchMAC( pIPSet ) && matchANID( pIPSet ) ) ) { char szTmp[128]; snprintf(szTmp, sizeof(szTmp), "Ignore DISCOVERY_SET for AN %u MAC", ntohl(pIPSet->m_unAnId) ); szTmp[ sizeof(szTmp) - 1 ] = 0; LOG_HEX( szTmp, pIPSet->m_uchMAC_Address, sizeof(pIPSet->m_uchMAC_Address) ); return false; } ConfigureNetwork(*pIPSet); update_rcnetinfo(RC_NET_INFO, pIPSet->m_unIP_ethInterf, pIPSet->m_unMask_ethInterf, pIPSet->m_unDefaultGateway, p_stClientAddr); //memset(p, 0, BUFLEN); fillDiscoveryResponse(); return true; // instruct caller to send the reply back } case DISCOVERY_REPLY: { LOG("Ignore DISCOVERY_REPLY"); return false; } default: { LOG("ERROR processData() unknown MessageType %u", *uchMesssageType); return false; } } }
/* cgiReadFile() * * Read and save a file from a multipart request * another case to look for, when 0x0D is seen as the last * character in the buffer, then the whole buffer should be * commited, and retry the search */ char *CGI::ReadFile (char *boundary, int& contentLength) { size_t boundaryLen; char tmpl[]= NIVIS_TMP"cgi_file_upload_XXXXXX"; FILE *tmpfile; int fd; boundaryLen = strlen(boundary); FLOG("BOUNDARY[%s]", boundary); int startContentLength = contentLength ; if ( -1 == (fd = mkstemp (tmpl)) ) { log2flash("CGI: cgiReadFile failed: Unable to mkstemp"); return NULL; } if ((tmpfile = fdopen (fd, "w")) == NULL) { unlink (tmpl); log2flash("CGI: cgiReadFile failed: Unable to fdopen tmpfile"); return NULL; } FLOG("contentLength[%d]", contentLength); log2flash("CGI: cgiReadFile expecting %u bytes", contentLength); while (contentLength > 0 && !feof (io.input)) { size_t boundaryOffset =0 ; char rdBuf[8*1024]; struct timeval timeout={5,0}; fd_set readfds, errfds; FD_ZERO(&readfds); FD_ZERO(&errfds); FD_SET( fileno(io.input), &readfds ); FD_SET( fileno(io.input), &errfds ); int rv=select(fileno(io.input)+1, &readfds, NULL, &errfds, &timeout); if ( -1 == rv || FD_ISSET(fileno(io.input), &errfds) ) { FPERR("select failed"); break ; } if ( 0== rv || ! FD_ISSET( fileno(io.input), &readfds) ) { LOG("FILE is not readable"); continue; } ssize_t ssize = peek( fileno(io.input), rdBuf, sizeof(rdBuf) ); if ( ssize <= 0 ) break ; size_t size = (size_t)ssize; LOG("Size:%i contentLength:%i", size, contentLength); if ( boundaryOffset ) { if ( ! strncmp( rdBuf, boundary+boundaryOffset, _Min( strlen(boundary)-boundaryOffset, size)) ) { boundaryOffset+=_Min( strlen(boundary)-boundaryOffset, size); if ( boundaryOffset==boundaryLen) { LOG("Rest of boundary found[%s] -> exit", rdBuf ); boundaryOffset = 0 ; break; } else { LOG("Still looking for boundary"); continue ; } } else { LOG("Rest of partial match not found -> commit all data. (rb:%i contentLength:%i)", size, contentLength); fcopy_s(tmpfile, fileno(io.input), size, contentLength); boundaryOffset = 0 ; } } int boundaryStart = searchodoa(rdBuf, size); if ( boundaryStart <0 ) { fcopy_s(tmpfile, fileno(io.input), size, contentLength); LOG("No 0x0D/0x0A seen -> commit all data (rb:%i contentLength:%i)", size, contentLength ); continue; } else { if ( ! strncmp( rdBuf+boundaryStart+2, boundary, _Min(size,boundaryLen)) ) { // read from socket until boundary begins // write the read data to disk so we can use // rdBuf to reconstruct the boundary boundaryOffset = _Min(size,boundaryLen) ; if ( boundaryOffset >= boundaryLen ) { size_t plus=0, finalsz=size; if ( ! strncmp("--\x0d\x0a",rdBuf+boundaryStart+2+boundaryLen,4) ) { LOG("Final boundary found -> commit all data and exit (contentLength:%i)", contentLength ); plus=4; finalsz=sizeof(rdBuf); } ssize_t rb = read( fileno(io.input), rdBuf, finalsz ); if ( rb <=0 ) { LOG_ERR("Smth went wrong"); break ; } for ( size_t wb=0; wb < rb-boundaryLen-2-plus/*0d0a*/; ) { wb += fwrite( rdBuf+wb, sizeof(char), (rb-boundaryLen-2-plus)-wb, tmpfile); } contentLength -= rb ; LOG("Boundary found comit data until boundaryStart (rb:%i contentLength:%i)", rb, contentLength); break ; } else { // needs testing, hard to hit branch LOG("Partial match -> need more data. comit data before boundaryStart (contentLength:%i)", contentLength ); //consume until boundary begins fcopy_s( tmpfile, fileno(io.input), boundaryStart-1, contentLength) ; continue ; } } else { fcopy_s(tmpfile, fileno(io.input), size, contentLength); LOG("Reached end of buffer-> commit all data. (rb:%i contentLength:%i)", size, contentLength); continue; } } } fclose_s (tmpfile); FLOG("cgiReadFile[%u]B tmpFile:[%s] contentLengthLeft[%d]B", startContentLength-contentLength, tmpl, contentLength); //log2flash("CGI: cgiReadFile[%u]B tmpFile[%s] contentLengthLeft[%d]", startContentLength-contentLength, tmpl, contentLength); if (contentLength) { ERR("cgiReadFile incomplete dl -> unlink(tmpFile:[%s])", tmpl); log2flash("ERR:cgiReadFile incomplete dl -> unlink(tmpFile:[%s])", tmpl); unlink(tmpl); return NULL; } return strdup (tmpl); }
/** * * @return */ static int handleMultipartForm(conn_t*cli_cn) { FLOG("multipart/formdata"); char **vars, *tmp ; CGI cgi(cli_cn->jsonRPC->io) ; if ( ! cgi.Init( ) ) { ERR("Unable to InitCGI"); return false ; } CFileLock oLock(UPGRADE_LOCK); int nSecLeft = oLock.ForceOldLock(5*60); //use 5minutes without upload time and 15minutes with upload time // try to obtain the lock if (nSecLeft) { char szMsg[1024]; sprintf(szMsg,"FW upgrade in progress please try again in %d minutes", nSecLeft/60 + 1); LOG(szMsg); cli_cn->jsonRPC->JsonError(szMsg,true) ; return true ; } //Remove _UPLOAD_TMP first #if (defined(HW_VR900) or defined(HW_CAMBRIA)) if ( ! access(_UPLOAD_TMP, R_OK|W_OK) ) #else if ( ! faccessat(AT_FDCWD, _UPLOAD_TMP, R_OK|W_OK, AT_EACCESS) ) #endif { log2flash("CGI: dir "_UPLOAD_TMP" was not previously deleted"); if ( system("rm -rf "_UPLOAD_TMP"* &>/dev/null" ) == -1 ) { cli_cn->jsonRPC->JsonError("Unable remove temporary dir", true) ; }; } // Recreate _UPLOAD_TMP // char s[100]; // getcwd(s, 100); // FPERR("cwd: %s", s); // FPERR("uid(%d),euid(%d), access("_UPLOAD_TMP", R_OK|W_OK) = %d", getuid(), geteuid(), access(_UPLOAD_TMP, R_OK|W_OK)); #if (defined(HW_VR900) or defined(HW_CAMBRIA)) if ( access(_UPLOAD_TMP, R_OK|W_OK) && mkdir(_UPLOAD_TMP , 0777) ) #else if ( faccessat(AT_FDCWD, _UPLOAD_TMP, R_OK|W_OK, AT_EACCESS) && mkdir(_UPLOAD_TMP , 0777) ) #endif { FLOG("Unable to make dir "_UPLOAD_TMP); cli_cn->jsonRPC->JsonError("Unable create temporary dir", true) ; exit(EXIT_FAILURE); } /***************************************************************/ // get the file first then act uppon it vars = cgi.GetFiles (); if (vars) { s_file *file; for (int i=0; vars[i] != NULL; i++) { file = cgi.GetFile (vars[i]); if ( !file ) { FLOG("Unable to get file"); continue ; } tmp = EscapeSgml (file->filename); free (tmp); if (file->type) { tmp = EscapeSgml (file->type); free (tmp); } char dstfile[PATH_MAX]={0,}; snprintf(dstfile, PATH_MAX, _UPLOAD_TMP"%s", file->filename ); FLOG("FILE:[%s]", dstfile); //workaround: on Ubuntu 10.04 the file we are about to rename() will disappear after the rename(), unless we sleep here! usleep(50000); if (rename(file->tmpfile, dstfile)) { cli_cn->jsonRPC->JsonError("Unable to rename file", true); return false ; } log2flash("CGI: %s uploaded [%s]", cli_cn->jsonRPC->io.env.Get("REMOTE_ADDR"), dstfile ) ; } cgi.FreeList (vars); } else { LOG("No Files") ; } /***************************************************************/ /***************************************************************/ vars = cgi.GetVariables (); if (vars) { memset(cli_cn->req, 0, sizeof(cli_cn->req) ) ; for (int i=0,k=0; vars[i] != NULL; i++) { if ( strncmp( "call", vars[i], 4) ) continue ; char *val = cgi.GetValue (vars[i]); if ( !val ) { WARN("Unable to get variable"); continue ; } while ( val && isspace(*val) ) val++ ; if ( '\0' == *val ) continue ; //valgrind on rpc.cgi cries over this, but it doesn't really matter, because rpc.cgi is short lived //The long lived scgi_svc frees this memory in conn_t::close() //TODO: free it the right way, in the callers of jsonRPC->HandleCall() char *req = strdup(val) ; if ( ! req ) continue ; FLOG("var[%s] req:[%s]", vars[i], val) ; cli_cn->req[k++] = req; } cgi.FreeList (vars); }else { FLOG("No variables"); } cgi.Free (); if (unlink(UPGRADE_LOCK)) LOG_ERR("upload unlink(%s)",UPGRADE_LOCK); oLock.Unlock(); cli_cn->callTop = true ; return true ; }
void HandlerFATAL(int p_signal) { static char str[4098]; /// 11 bytes per address. Watch for overflow int i; int n=0, bContinue=1 ; // used by BKTRACE macro *str=0;/// reset every time // ARM/CYG has an older uClibc with no program_invocation_short_name support // so use __progname #if defined(ARM) || defined(CYG) extern const char *__progname; #endif for ( i=0; bContinue && (i<16) ; ++i) { switch (i) /// parameter for __builtin_frame_address must be a constant integer { case 0: BKTRACE(0,n,bContinue); break ; // ARM doesn't support more than 1 stack unwind. #if !defined(ARM) && !defined(CYG) case 1: BKTRACE(1,n,bContinue); break ; case 2: BKTRACE(2,n,bContinue); break ; case 3: BKTRACE(3,n,bContinue); break ; case 4: BKTRACE(4,n,bContinue); break ; case 5: BKTRACE(5,n,bContinue); break ; case 6: BKTRACE(6,n,bContinue); break ; case 7: BKTRACE(7,n,bContinue); break ; case 8: BKTRACE(8,n,bContinue); break ; case 9: BKTRACE(9,n,bContinue); break ; case 10:BKTRACE(10,n,bContinue); break ; case 11:BKTRACE(11,n,bContinue); break ; case 12:BKTRACE(12,n,bContinue); break ; case 13:BKTRACE(13,n,bContinue); break ; case 14:BKTRACE(14,n,bContinue); break ; case 15:BKTRACE(15,n,bContinue); break ; #elif defined(ARM) case 1: n+=snprintf( str+n, sizeof(str)-n-1, "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " "%08x %08x %08x %08x %08x %08x %08x %08x " ); break; #endif } } log2flash("PANIC [%s] Pid[%lu] %s %u. Backtrace [%s]", // ARM/CYG has an older uClibc with no program_invocation_short_name support // so use __progname #if !defined(ARM) && !defined(CYG) program_invocation_short_name, #else __progname, #endif getpid(), (p_signal == SIGSEGV) ? "SIGSEGV" : (p_signal == SIGABRT) ? "SIGABRT" : (p_signal == SIGFPE) ? "SIGFPE" :"UNK", p_signal, str); /// make sure to flush the log to disk. Standard LOG does it at this time. Put an extra \n to be absolutely sure LOG("PANIC [%s] Pid[%lu] %s %u. Backtrace [%s]\n", #if !defined(ARM) && !defined(CYG) program_invocation_short_name, #else __progname, #endif getpid(), (p_signal == SIGSEGV) ? "SIGSEGV" : (p_signal == SIGABRT) ? "SIGABRT" : (p_signal == SIGFPE) ? "SIGFPE" : "UNK", p_signal, str); exit(EXIT_FAILURE); }