Bezüglich der for-loops: Alles klar. Mit Null anfangen kann auch in bash sinnvoll sein, wenn man nämlich z.B. die loop-Variable auch als index für arrays nutzen will (welche ja bekanntlich bei 0 anfangen). Beispiel: "arr=(eins zwei drei vier fünf) && for ((i=0; i<5; i++)); do echo ${arr[$i]}; done" (Normalerweise macht man ja in bash keinen Loop, um einen array nach stdout zu schreiben, soll nur ein einfaches Beispiel sein.)
Zurück zu C:
Wenn ich es richtig verstehe, hätte ich den bug mit read nicht, wenn ich fgets nutzen würde? Dann sollte ich das vielleicht doch machen und mir mein Beispiel mit read aufheben für Anwendungszwecke, bei denen ich mehrere Zeilen aus der fifo auf einmal lesen möchte.
Dann würde das Programm so aussehen?
Code: Alles auswählen
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <X11/Xlib.h>
/* BEGIN: user configuration */
static const char program_name[] = "myxd";
/* static const char fifo[] = "/tmp/dwmblocks_fifo_intern"; */
static const char fifo[] = "/home/user/fifo";
/* END: user configuration */
static int finish;
static void
term_hdl (int signum)
{
/* if we do not use signum, gcc complains */
if (signum == SIGTERM) {
finish = 1;
}
}
int
main(void)
{
static char *display_name = NULL;
static char name[BUFSIZ];
static FILE *in;
static int screen;
static int state = EXIT_SUCCESS;
static Window root;
static Display *dpy;
static struct sigaction term_act;
static XEvent ev;
memset(&term_act, 0, sizeof(term_act));
term_act.sa_handler = term_hdl;
if (sigaction(SIGTERM, &term_act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
dpy = XOpenDisplay(display_name);
if (dpy == NULL) {
fprintf(stderr, "%s: unable to open display '%s'\n",
program_name, XDisplayName(display_name));
exit(EXIT_FAILURE);
}
root = RootWindow(dpy, screen);
in = fopen(fifo, "r+");
if (in == NULL) {
perror("fopen");
XCloseDisplay(dpy);
exit(EXIT_FAILURE);
}
while (finish == 0) {
while (XPending(dpy)) {
XNextEvent(dpy, &ev);
}
memset(name, 0, sizeof(name));
if (fgets(name, sizeof(name), in) == NULL) {
/* perror("fgets");
state = EXIT_FAILURE; */
break;
} else {
/* remove trailing newline */
if ((*name) && (name[strlen(name)-1] == '\n')) {
name[strlen(name)-1] = '\0';
}
XStoreName(dpy, root, name);
}
}
fclose(in);
XCloseDisplay(dpy);
exit(state);
}
Rückgabewert von sigaction is int, wird gegen 0 verglichen
"dpy" ist pointer, wird gegen NULL vergleichen
"in" ist pointer, wird gegen NULL vergleichen
"finish" ist int, wird gegen 0 verglichen
Rückgabewert von XPending ist int, wird von while wie boolean behandelt (ich habe das jetzt erstmal gelassen, weil ich mit den Überlegungen zum X Code noch nicht fertig bin)
Rückgabewert von fgets ist im Fehlerfall NULL:
Manpage von fgets hat geschrieben:fgets() returns s on success, and NULL on error or when end of file occurs while no characters have been read.
Leider beklagt sich fgets bei kill über "interrupted system call", wenn ich die perror-Zeile nicht kommentiere.
Und bei fgets kein "sizeof(name)-1", ich habe dran gedacht!
@meillo: Deine Anmerkung zu den geschweiften Klammern finde ich sehr sinnvoll. Ich habe das schon in patches gesehen, wie dann die if-/for-/while-Zeilen mit getauscht werden müssen, weil die Klammer angehängt werden muss. Für den Patch-Leser ist das nicht so angenehm...
Übrigens: Die geschweifte Klammer in meinem letzten if ist gerade das 80. Zeichen in der Zeile.