#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
+#include <fcntl.h>
#ifdef HAVE_ICONV
#include <iconv.h>
double last_update;
float interval;
char *buffer;
+ /* If not -1, a file descriptor to read from when
+ * logfile is a FIFO. */
+ int fd;
} tail;
struct {
END OBJ(tail, 0)
char buf[64];
int n1, n2;
+ struct stat st;
if (!arg) {
ERR("tail needs arguments");
obj->type = OBJ_text;
return NULL;
} else {
FILE *fp = NULL;
- fp = fopen(buf, "r");
- if (fp) {
+ int fd;
+
+ obj->data.tail.fd = -1;
+
+ if (stat(buf, &st) == 0) {
+ if (S_ISFIFO(st.st_mode)) {
+ fd = open(buf, O_RDONLY|O_NONBLOCK);
+
+ if (fd == -1)
+ CRIT_ERR("tail logfile does not exist, or you do not have correct permissions");
+
+ obj->data.tail.fd = fd;
+
+ }
+ else
+ fp = fopen(buf, "r");
+ }
+
+ if (fp || obj->data.tail.fd != -1) {
obj->data.tail.logfile =
malloc(text_buffer_size);
strcpy(obj->data.tail.logfile, buf);
obj->data.tail.wantedlines = n1;
obj->data.tail.interval =
update_interval * 2;
- fclose(fp);
+
+ if (obj->data.tail.fd == -1)
+ fclose(fp);
} else {
//fclose (fp);
CRIT_ERR("tail logfile does not exist, or you do not have correct permissions");
return NULL;
} else {
FILE *fp;
- fp = fopen(buf, "r");
- if (fp != NULL) {
+ int fd;
+
+ obj->data.tail.fd = -1;
+
+ if (stat(buf, &st) == 0) {
+ if (S_ISFIFO(st.st_mode)) {
+ fd = open(buf, O_RDONLY|O_NONBLOCK);
+
+ if (fd == -1)
+ CRIT_ERR("tail logfile does not exist, or you do not have correct permissions");
+
+ obj->data.tail.fd = fd;
+ }
+ else
+ fp = fopen(buf, "r");
+ }
+
+ if (fp || obj->data.tail.fd != -1) {
obj->data.tail.logfile =
malloc(text_buffer_size);
strcpy(obj->data.tail.logfile, buf);
obj->data.tail.wantedlines = n1;
obj->data.tail.interval = n2;
- fclose(fp);
+
+ if (obj->data.tail.fd == -1)
+ fclose(fp);
} else {
//fclose (fp);
CRIT_ERR("tail logfile does not exist, or you do not have correct permissions");
free(object_list);
}
+/*
+ * Allows reading from a FIFO (i.e., /dev/xconsole). The file descriptor is
+ * set to non-blocking which makes this possible.
+ *
+ * FIXME
+ * Since lseek cannot seek a file descriptor long lines will break.
+ */
+static void tail_pipe(struct text_object *obj, char *dst, size_t dst_size)
+{
+#define TAIL_PIPE_BUFSIZE 4096
+ int lines = 0;
+ int line_len = 0;
+ int last_line = 0;
+ int fd = obj->data.tail.fd;
+
+ while (1) {
+ char buf[TAIL_PIPE_BUFSIZE];
+ ssize_t len = read(fd, buf, sizeof(buf));
+ int i;
+
+ if (len == -1) {
+ if (errno != EAGAIN) {
+ strcpy(obj->data.tail.buffer, "Logfile Read Error");
+ snprintf(dst, dst_size, "Logfile Read Error");
+ }
+
+ break;
+ }
+ else if (len == 0) {
+ strcpy(obj->data.tail.buffer, "Logfile Empty");
+ snprintf(dst, dst_size, "Logfile Empty");
+ break;
+ }
+
+ for (line_len = 0, i = 0; i < len; i++) {
+ int pos = 0;
+ char *p;
+
+ if (buf[i] == '\n') {
+ lines++;
+
+ if (obj->data.tail.readlines > 0) {
+ int n;
+ int olines = 0;
+ int first_line = 0;
+
+ for (n = 0; obj->data.tail.buffer[n]; n++) {
+ if (obj->data.tail.buffer[n] == '\n') {
+ if (!first_line)
+ first_line = n+1;
+
+ if (++olines < obj->data.tail.wantedlines) {
+ pos = n+1;
+ continue;
+ }
+
+ n++;
+ p = obj->data.tail.buffer + first_line;
+ pos = n - first_line;
+ memmove(obj->data.tail.buffer, obj->data.tail.buffer + first_line, strlen(p));
+ obj->data.tail.buffer[pos] = 0;
+ break;
+ }
+ }
+ }
+
+ p = buf + last_line;
+ line_len++;
+ memcpy(&(obj->data.tail.buffer[pos]), p, line_len);
+ obj->data.tail.buffer[pos + line_len] = 0;
+ last_line = i+1;
+ line_len = 0;
+ obj->data.tail.readlines = lines;
+ continue;
+ }
+
+ line_len++;
+ }
+ }
+
+ snprintf(dst, dst_size, "%s", obj->data.tail.buffer);
+}
+
static void generate_text_internal(char *p, int p_max_size, struct text_object *objs, unsigned int object_count, struct information *cur)
{
unsigned int i;
FILE *fp;
long nl=0, bsize;
int iter;
+
+ if (obj->data.tail.fd != -1) {
+ tail_pipe(obj, p, p_max_size);
+ goto head;
+ }
+
fp = fopen(obj->data.tail.logfile, "rt");
+
if (fp == NULL) {
/* Send one message, but do not consistently spam on
* missing logfiles. */
//parse_conky_vars(obj->data.tail.buffer, p, cur);
}
+head:
OBJ(head) {
if (current_update_time -obj->data.tail.last_update < obj->data.tail.interval) {
snprintf(p, p_max_size, "%s", obj->data.tail.buffer);
void get_ibm_acpi_volume( char * p_client_buffer, size_t client_buffer_size )
{
-/* get volume (0-14) on IBM/Lenovo laptops running the ibm acpi.
- "Volume" here is none of the mixer volumes, but a "master of masters"
- volume adjusted by the IBM volume keys.
- /proc/acpi/ibm/fan looks like this (4 lines):
+ /* get volume (0-14) on IBM/Lenovo laptops running the ibm acpi.
+ "Volume" here is none of the mixer volumes, but a "master of masters"
+ volume adjusted by the IBM volume keys.
+ /proc/acpi/ibm/fan looks like this (4 lines):
level: 4
mute: off
commands: up, down, mute
Peter Tarjan (ptarjan@citromail.hu)
*/
- if ( !p_client_buffer || client_buffer_size <= 0 )
- return;
+ if ( !p_client_buffer || client_buffer_size <= 0 )
+ return;
- FILE *fp;
+ FILE *fp;
- char volume[128];
- snprintf(volume, 127, "%s/volume",IBM_ACPI_DIR);
- unsigned int vol=-1;
- char mute[3]="";
+ char volume[128];
+ snprintf(volume, 127, "%s/volume",IBM_ACPI_DIR);
+ unsigned int vol=-1;
+ char mute[3]="";
- fp = fopen(volume, "r");
- if (fp != NULL)
- {
- while (!feof(fp))
+ fp = fopen(volume, "r");
+ if (fp != NULL) {
+ while (!feof(fp)) {
+ char line[256];
+ unsigned int read_vol = -1;
+ if (fgets(line, 255, fp) == NULL) break;
+ if (sscanf(line, "level: %d", &read_vol)) {
+ vol = read_vol;
+ continue;
+ }
+ if (sscanf(line, "level: %d", &vol)) continue;
+ if (sscanf(line, "mute: %s", mute)) break;
+ }
+ }
+ else
{
- char line[256];
- if (fgets(line, 255, fp) == NULL) break;
- if (sscanf(line, "level: %d", &vol)) continue;
- if (sscanf(line, "mute: %s", mute)) break;
+ CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", volume, strerror(errno));
}
- }
- else
- {
- CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", volume, strerror(errno));
- }
- fclose(fp);
+ fclose(fp);
- if (strcmp(mute, "on")==0)
- {
- snprintf( p_client_buffer, client_buffer_size, "%s", "mute" );
- return;
- }
- else
- {
- snprintf( p_client_buffer, client_buffer_size, "%d", vol );
- return;
- }
+ if (strcmp(mute, "on")==0)
+ {
+ snprintf( p_client_buffer, client_buffer_size, "%s", "mute" );
+ return;
+ }
+ else
+ {
+ snprintf( p_client_buffer, client_buffer_size, "%d", vol );
+ return;
+ }
}