/* ----------------------------------------------------------------------- */ bool bookmark_autobookmark(bool prompt_ok) { char* bookmark; bool update; if (!bookmark_is_bookmarkable_state()) return false; audio_pause(); /* first pause playback */ update = (global_settings.autoupdatebookmark && bookmark_exists()); bookmark = create_bookmark(); #if CONFIG_CODEC != SWCODEC /* Workaround for inability to speak when paused: all callers will just do audio_stop() when we return, so we can do it right away. This makes it possible to speak the "Create a Bookmark?" prompt and the "Bookmark Created" splash. */ audio_stop(); #endif if (update) return write_bookmark(true, bookmark); switch (global_settings.autocreatebookmark) { case BOOKMARK_YES: return write_bookmark(true, bookmark); case BOOKMARK_NO: return false; case BOOKMARK_RECENT_ONLY_YES: return write_bookmark(false, bookmark); } #ifdef HAVE_LCD_BITMAP const char *lines[]={ID2P(LANG_AUTO_BOOKMARK_QUERY)}; const struct text_message message={lines, 1}; #else const char *lines[]={ID2P(LANG_AUTO_BOOKMARK_QUERY), str(LANG_CONFIRM_WITH_BUTTON)}; const struct text_message message={lines, 2}; #endif if(prompt_ok && gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES) { if (global_settings.autocreatebookmark == BOOKMARK_RECENT_ONLY_ASK) return write_bookmark(false, bookmark); else return write_bookmark(true, bookmark); } return false; }
/* ----------------------------------------------------------------------- */ bool bookmark_create_menu(void) { return write_bookmark(true, create_bookmark()); }
/************************************************ * fetch_logfile( char *logfilename, char *bookmarkfile, int updbm_flag ) ************************************************ */ int fetch_logfile( char *logfile, char *bmfile, int updbm_flag ) { bookmark obm, nbm; /* old, new bookmark */ char *ibuf = NULL; /* input buf (--> the logfile) */ size_t ilen = 0; char *ipt = NULL; char *bmpt = NULL; /* points to first new char if bm exists */ char *obuf = NULL; /* output buf (filled backwards) */ int opos; /* first used char pos in obuf */ /* for CONV_NAGIOS3 */ int lastlinepos = 0; /* pos of beginning of lastline in obuf */ int lastlinelen = 0; /* len of lastline, excl. trailing '\' 'n' */ int r; /* write's returncode */ int i; int fd = -1; struct stat sb; char *lgfile = NULL; int llen = 0; int done = 0; if( read_bookmark( bmfile, &obm ) ) return RET_ERROR; if( (fd=open( logfile, O_RDONLY )) == -1 ) { perr( "open", logfile, errno ); return RET_ERROR; } if( fstat( fd, &sb ) == -1 ) { perr( "stat", logfile, errno ); close( fd ); return RET_ERROR; } nbm.last = (size_t) sb.st_size; nbm.mtime = sb.st_mtime; nbm.inode = sb.st_ino; /* something changed meanwhile ? */ if( obm.mtime==nbm.mtime && obm.inode==nbm.inode && obm.last==nbm.last ) { if( conv_G & CONV_OKMSG ) r = write( STDOUT_FILENO, OK_MESSAGE "\n", sizeof( OK_MESSAGE ) ); close( fd ); return RET_OK; } /*****************/ obuf = malloc( fetchlen_G+1 ); if( obuf == NULL ) { perr( "malloc", NULL, errno ); close( fd ); return RET_ERROR; } opos = fetchlen_G; *(obuf + opos) = '\0'; /* dummy: opos -> first used char in obuf */ if( conv_G & CONV_NEWLINE ) { /* when using CONV_NEWLINE the obuf is filled up like this: 1. init: write '\\' 'n' '\n' to the end (3 chars) 2. fill (copyline() ) by first prepend line contents and then prepend '\\' 'n' result: An additional '\\' 'n' at the beginning else 1. fill (copyline() ) by first prepend newline and then prepend line contents */ *(obuf + --opos) = '\n'; *(obuf + --opos) = 'n'; *(obuf + --opos) = '\\'; } lgfile = (char*)malloc( strlen(logfile) + sizeof(".X") ); if( lgfile == NULL ) { free( obuf ); perr( "malloc", NULL, errno ); close( fd ); return RET_ERROR; } /* read in all logfiles and backward fill obuf upto fetchlen_G chars */ for( i=-1; i<10; i++ ) { /* i==-1: logfile without suffix, else i==logfile suffix */ if( i==-1 ) { /* lgfile is already open and sb contains the stat */ strcpy( lgfile, logfile ); }else{ sprintf( lgfile, "%s.%1d", logfile, i ); if( (fd=open( lgfile, O_RDONLY )) == -1 ) { if( errno==ENOENT && i==0 ) { continue; /* some logrotator start with .1 */ }else if( errno==ENOENT && i>0 ) { break; }else{ perr( "open", lgfile, errno ); free( obuf ); free( lgfile ); return RET_ERROR; } } if( fstat( fd, &sb ) == -1 ) { perr( "stat", lgfile, errno ); free( obuf ); free( lgfile ); close( fd ); return RET_ERROR; } } ilen = (size_t) sb.st_size; if( ilen == 0 ) { close( fd ); if( obm.inode == sb.st_ino ) break; continue; } ibuf = mmap( NULL, ilen, PROT_READ, MAP_SHARED, fd, (off_t)0 ); if( ibuf == MAP_FAILED ) { perr( "mmap", lgfile, errno ); free( obuf ); free( lgfile ); close( fd ); return RET_ERROR; } #ifdef HAS_MADVISE if( madvise( ibuf, ilen, MADV_RANDOM ) ) { perr( "madvise", NULL, errno ); free( obuf ); free( lgfile ); close( fd ); munmap( ibuf, ilen ); return RET_ERROR; } #endif /* check for old bookmark */ bmpt = NULL; if( obm.inode == sb.st_ino ) { bmpt = ibuf+obm.last; } /* scan backwards for lines but the first */ done = 0; for( llen=1,ipt=ibuf+ilen-2; ipt>=ibuf; llen++,ipt-- ) { if( *ipt=='\n' ) { if( ipt+1<bmpt ) { done=1; break; } opos = copyline( opos, obuf, ipt+1, llen ); if( opos==0 ) { done=1; break; } llen = 0; } } /* copy first line ? */ if( ipt+1==ibuf && done==0 ) { if( ipt+1<bmpt ) { done=1; } else{ opos = copyline( opos, obuf, ipt+1, llen ); } if( opos==0 ) { done=1; } } munmap( ibuf, ilen ); close( fd ); if( done ) break; if( bmpt ) break; /* processed a bookmarked file? --> finito */ } if( updbm_flag ) { if( write_bookmark( bmfile, &nbm ) ) return RET_ERROR; } /* if in Nagios3 mode: prepend short message (the last line fetched) */ if( conv_G & CONV_NAGIOS3 ) { /* Nagios2 --> Nagios3 changed accepted format for plugin output. * Nagios2 accepted a line containing one or more '\'+'n' as a single * line. Nagios3 now supports multiline output, and as a result, lines * containing '\'+'n' are now handled as multiline messages (as well as * messages having '\n'). The new multiline format is: * SHORT_MESSAGE | OPTIONAL_PERFORMANCE_DATA * LONG_MESSAGE_LINE_1 * LONG_MESSAGE_LINE_2 * ... * LONG_MESSAGE_LINE_N * * In Nagios3 mode fetchlog copies LONG_MESSAGE_LINE_N as SHORT_MESSAGE * and leaves OPTIONAL_PERFORMANCE_DATA empty */ int oidx = fetchlen_G - 4; /* in obuf: last char, last line */ lastlinepos = oidx + 1; /* fallback value: empty line at end */ lastlinelen = 0; /* fallback value: empty line at end */ /* determine lastlinepos and lastlinelen */ while( oidx > 0 ) { if( *(obuf + oidx) == 'n' && *(obuf + oidx -1) == '\\' ) { lastlinepos = oidx + 1; lastlinelen = fetchlen_G - lastlinepos - 3; /* 3: \ n \n */ break; } oidx--; } /* case: obuf has enough room for SHORT_MESSAGE */ if( lastlinelen + 1 <= opos ) { /* +1 = '|' */ *(obuf + --opos) = '|'; memmove( obuf+opos-lastlinelen, obuf+lastlinepos, lastlinelen ); opos -= lastlinelen; /* case: obuf too small: SHORT_MESSAGE and fetched messages overlap, * but not LONG_MESSAGE_LINE_N */ }else if( lastlinelen + 6 <= lastlinepos ) { /* +6 = '|\n...' */ memmove( obuf, obuf+lastlinepos, lastlinelen ); *(obuf + lastlinelen + 0 ) = '|'; *(obuf + lastlinelen + 1 ) = '\\'; *(obuf + lastlinelen + 2 ) = 'n'; *(obuf + lastlinelen + 3 ) = '.'; *(obuf + lastlinelen + 4 ) = '.'; if( *(obuf + lastlinelen + 5 ) != '\\' ) { *(obuf + lastlinelen + 5 ) = '.'; } opos = 0; /* case: obuf too small: SHORT_MESSAGE and fetched messages overlap, * including LONG_MESSAGE_LINE_N */ }else{ memmove( obuf+lastlinepos+2, obuf+lastlinepos, lastlinelen ); opos = lastlinepos + 2; } } /* only return a message if there is something to print */ if( ((conv_G & CONV_NEWLINE)==0 && fetchlen_G-opos==0 ) || ((conv_G & CONV_NEWLINE)!=0 && ( ((conv_G & CONV_NAGIOS3)== 0 && fetchlen_G-opos==3 ) || ((conv_G & CONV_NAGIOS3)!= 0 && fetchlen_G-opos==4 ) ) ) ) { if( conv_G & CONV_OKMSG ) { r = write( STDOUT_FILENO, OK_MESSAGE "\n", sizeof( OK_MESSAGE ) ); } i = RET_OK; }else{ r = write( STDOUT_FILENO, obuf+opos,fetchlen_G-opos); i = RET_NEWMSG; } free( obuf ); free( lgfile ); return i; } /* fetch_logfile() */