This file is indexed.

/usr/share/emacs/site-lisp/emacs-goodies-el/tail.el is in emacs-goodies-el 35.12.

This file is owned by root:root, with mode 0o655.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
;;; tail.el --- Tail files within Emacs

;; Copyright (C) 1989, 1990, 1994, 1998 Free Software Foundation, Inc.
;; (For appt.el code)
;; Copyright (C) 2000 Benjamin Drieu

;; Author: Benjamin Drieu <bdrieu@april.org>
;; Keywords: tools

;; This file is NOT part of GNU Emacs.

;; This program as GNU Emacs are free software; you can redistribute
;; them and/or modify them under the terms of the GNU General Public
;; License as published by the Free Software Foundation; either
;; version 2, or (at your option) any later version.

;; They are distributed in the hope that they will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with them; see the file COPYING.  If not, write to the Free
;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
;; 02111-1307, USA.

;;  $Id: tail.el,v 1.4 2010-07-28 15:50:01 psg Exp $

;;; Commentary:

;;  This program displays ``tailed'' contents of files inside transients
;;  windows of Emacs.  It is primarily meant to keep an eye on logs within
;;  Emacs instead of using additional terminals.

;;  Historical URL for tail.el is
;;    http://inferno.cs.univ-paris8.fr/~drieu/emacs/
;;  Active developement URL is
;;    http://cvs.alioth.debian.org/cgi-bin/cvsweb.cgi/emacs-goodies-el/elisp/emacs-goodies-el/?cvsroot=pkg-goodies-el

;;; History:
;;
;;  2003-10-09 Peter S Galbraith <psg@debian.org>
;;   - minor checkdoc-suggested changes.
;;   - tail-hide-window: Bug fix. Would kill all but one window when more than
;;      one window was visible prior to the tail window being displayed.
;;      copied code from appt.el appt-delete-window.
;;   - Fix boolean defcustoms.
;;   - Make it work on XEmacs (only briefly tested).
;;
;;  2010-06-05 Kevin Ryde <user42@zip.com.au>
;;   - timer object in a per-buffer variable for new output (Closes: #584598).

;;; Code:

;;  Custom variables (may be set by the user)

(defgroup tail nil
  "Tail files or commands into Emacs buffers."
  :prefix "tail-"
  :group 'environment)

(defcustom tail-volatile t
  "Whether to erase previous output."
  :type 'boolean
  :group 'tail)

(defcustom tail-audible nil
  "Whether to produce a bell when some output is displayed."
  :type 'boolean
  :group 'tail)

(defcustom tail-raise nil
  "Whether to raise current frame when displaying (could be *very* annoying)."
  :type 'boolean
  :group 'tail)

(defcustom tail-hide-delay 5
  "Time in seconds before a tail window is deleted."
  :type 'integer
  :group 'tail)

(defcustom tail-max-size 5
  "Maximum size of the window."
  :type 'integer
  :group 'tail)


;; Functions

(defvar tail-timer nil)
(make-variable-buffer-local 'tail-timer)

;; Taken from calendar/appt.el
(defun tail-disp-window (tail-buffer tail-msg)
  "Display some content specified by TAIL-MSG inside buffer TAIL-BUFFER.
Create this buffer if necessary and put it inside a newly created window on
the lowest side of the frame."

  (require 'electric)

  ;; Make sure we're not in the minibuffer
  ;; before splitting the window.

  (if (equal (selected-window) (minibuffer-window))
      (if (other-window 1)
	  (select-window (other-window 1))
	(if window-system
	    (select-frame (other-frame 1)))))

  (let* ((this-buffer (current-buffer))
	 (this-window (selected-window))
	 (tail-disp-buf (set-buffer (get-buffer-create tail-buffer))))

    (if (cdr (assq 'unsplittable (frame-parameters)))
	;; In an unsplittable frame, use something somewhere else.
	(display-buffer tail-disp-buf)
      (unless (or (and (fboundp 'special-display-p)
                       (special-display-p (buffer-name tail-disp-buf)))
                  (and (fboundp 'same-window-p)
                       (same-window-p (buffer-name tail-disp-buf)))
		  (get-buffer-window tail-buffer))
	;; By default, split the bottom window and use the lower part.
	(tail-select-lowest-window)
	(split-window))
      (pop-to-buffer tail-disp-buf))

    (toggle-read-only 0)
    (if tail-volatile
	(erase-buffer))
    (insert-string tail-msg)
    (toggle-read-only 1)
    (shrink-window-if-larger-than-buffer (get-buffer-window tail-disp-buf t))
    (if (> (window-height (get-buffer-window tail-disp-buf t)) tail-max-size)
	(shrink-window (- (window-height (get-buffer-window tail-disp-buf t)) tail-max-size)))
    (set-buffer-modified-p nil)
    (if tail-raise
	(raise-frame (selected-frame)))
    (select-window this-window)
    (if tail-audible
	(beep 1))
    (when tail-hide-delay
      (if tail-timer
          (cancel-timer tail-timer))
      (setq tail-timer (run-with-timer tail-hide-delay nil
                                       'tail-hide-window tail-buffer)))))

(defun tail-hide-window (buffer)
  (with-current-buffer buffer
    (kill-local-variable 'tail-timer)) ;; the now expired timer object
  (let ((window (get-buffer-window buffer t)))
    (and window
	 (or (eq window (frame-root-window (window-frame window)))
	     (delete-window window)))))

(defun tail-select-lowest-window ()
  "Select the lowest window on the frame."
  (if (fboundp 'frame-lowest-window)
      (select-window (frame-lowest-window))
    (let* ((lowest-window (selected-window))
           (bottom-edge (car (cdr (cdr (cdr (window-edges))))))
           (last-window (previous-window))
           (window-search t))
      (while window-search
        (let* ((this-window (next-window))
               (next-bottom-edge (cadr (cddr (window-edges this-window)))))
          (when (< bottom-edge next-bottom-edge)
            (setq bottom-edge next-bottom-edge)
            (setq lowest-window this-window))
          (select-window this-window)
          (when (eq last-window this-window)
            (select-window lowest-window)
            (setq window-search nil)))))))

;;;###autoload
(defun tail-file (file)
  "Tails FILE specified with argument FILE inside a new buffer.
FILE *cannot* be a remote file specified with ange-ftp syntax because it is
passed to the Unix tail command."
  (interactive "Ftail file: ")
  ;; TODO: what if file is remote (i.e. via ange-ftp)
  (tail-command "tail" "-f" file))

;;;###autoload
(defun tail-command (command &rest args)
  "Tails COMMAND with arguments ARGS inside a new buffer.
It is also called by `tail-file'"
  (interactive "sTail command: \neToto: ")
  (let ((process
	 (apply 'start-process-shell-command
		command
		(concat "*Tail: "
			command
			(if args " " "")
			(mapconcat 'identity args " ")
			"*")
		command
		args)))
    (set-process-filter process 'tail-filter)))

(defun tail-filter (process line)
  "Tail filter called when some output comes."
  (tail-disp-window (process-buffer process) line))

(provide 'tail)

;;; tail.el ends here