+ if (fline >= max_fline)
+ fline = max_fline - 1;
+
+ /* also catches empty file (max_fline == 0) */
+ if (fline < 0)
+ return 0;
+
+ return LINENO(flines[fline]) + 1;
+}
+
+/* count number of lines in file */
+static void update_num_lines(void)
+{
+ int count, fd;
+ struct stat stbuf;
+ ssize_t len, i;
+ char buf[4096];
+
+ /* only do this for regular files */
+ if (num_lines == REOPEN_AND_COUNT || num_lines == REOPEN_STDIN) {
+ count = 0;
+ fd = open("/proc/self/fd/0", O_RDONLY);
+ if (fd < 0 && num_lines == REOPEN_AND_COUNT) {
+ /* "filename" is valid only if REOPEN_AND_COUNT */
+ fd = open(filename, O_RDONLY);
+ }
+ if (fd < 0) {
+ /* somebody stole my file! */
+ num_lines = NOT_REGULAR_FILE;
+ return;
+ }
+ if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) {
+ num_lines = NOT_REGULAR_FILE;
+ goto do_close;
+ }
+ while ((len = safe_read(fd, buf, sizeof(buf))) > 0) {
+ for (i = 0; i < len; ++i) {
+ if (buf[i] == '\n' && ++count == MAXLINES)
+ goto done;
+ }
+ }
+ done:
+ num_lines = count;
+ do_close:
+ close(fd);
+ }