Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Example program for io_glib binding.
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : *
8 : * For an example of how I/O bindings are used please see src/libs/notification/example.
9 : *
10 : * This example uses two I/O operations:
11 : * - The "input" operation is a file descriptor watcher that waits for
12 : * STDIN_FILENO (stdin) to become readable.
13 : * Since input is buffered, this typically happens when the user enters some
14 : * text and presses return.
15 : * In practice code using the I/O binding will attach non-blocking file
16 : * descriptors (e.g. from sockets).
17 : * - The "output" operation is a timer that prints the last read data every
18 : * second.
19 : *
20 : */
21 : #include <errno.h> // error handling
22 : #include <stdio.h> // printf
23 : #include <string.h> // memset & memcpy
24 : #include <unistd.h> // file descriptor numbers (STDIN_FILENO)
25 :
26 : #include <kdbassert.h> // assertions (ELEKTRA_NOT_NULL)
27 : #include <kdbhelper.h> // malloc & free
28 : #include <kdbio.h> // I/O binding functions (elektraIo*)
29 : #include <kdbio/glib.h> // I/O binding constructor for glib (elektraIoGlibNew)
30 :
31 : #include <glib.h> // glib functions
32 :
33 : #define BUFFER_LENGTH 255
34 : #define ONE_SECOND 1000
35 :
36 : GMainLoop * loop;
37 :
38 : ElektraIoInterface * binding;
39 : ElektraIoFdOperation * input;
40 : ElektraIoTimerOperation * output;
41 :
42 0 : int min (int a, int b)
43 : {
44 0 : return (a > b) ? b : a;
45 : }
46 :
47 0 : void stopLoop (void)
48 : {
49 : // Cleanup
50 0 : elektraIoBindingRemoveFd (input);
51 0 : elektraIoBindingRemoveTimer (output);
52 0 : elektraFree (input);
53 0 : elektraFree (output);
54 0 : elektraIoBindingCleanup (binding);
55 :
56 0 : g_main_loop_quit (loop);
57 0 : }
58 :
59 0 : void readText (ElektraIoFdOperation * fdOp, int flags ELEKTRA_UNUSED)
60 : {
61 0 : printf ("input: file descriptor became readable\n");
62 :
63 0 : char * lastInput = elektraIoFdGetData (fdOp);
64 0 : ELEKTRA_NOT_NULL (lastInput);
65 :
66 : char buffer[BUFFER_LENGTH];
67 0 : int bytesRead = read (elektraIoFdGetFd (fdOp), &buffer, BUFFER_LENGTH);
68 0 : if (bytesRead != -1)
69 : {
70 : // make sure there is a null terminator in buffer
71 0 : buffer[min (BUFFER_LENGTH - 1, bytesRead + 1)] = 0;
72 : // remove newline from string
73 0 : buffer[strcspn (buffer, "\r\n")] = 0;
74 : // copy to lastInput
75 0 : memcpy (lastInput, buffer, BUFFER_LENGTH);
76 : }
77 : else
78 : {
79 0 : int error = errno;
80 0 : if (error != EINTR)
81 : {
82 0 : printf ("input: I/O error occurred - exiting\n");
83 0 : stopLoop ();
84 : }
85 : }
86 0 : }
87 :
88 0 : void printText (ElektraIoTimerOperation * timerOp)
89 : {
90 0 : char * lastInput = elektraIoTimerGetData (timerOp);
91 0 : ELEKTRA_NOT_NULL (lastInput);
92 :
93 0 : if (strcmp (lastInput, "exit") == 0)
94 : {
95 0 : printf ("timer: stopping\n");
96 0 : stopLoop ();
97 : }
98 : else
99 : {
100 0 : if (strlen (lastInput) > 0)
101 : {
102 0 : printf ("timer: last text was \"%s\"\n", lastInput);
103 : }
104 : else
105 : {
106 0 : printf ("timer: text is empty\n");
107 : }
108 : }
109 0 : }
110 :
111 0 : int main (void)
112 : {
113 : // Initialize buffer
114 : char lastInput[BUFFER_LENGTH];
115 0 : memset (lastInput, 0, BUFFER_LENGTH);
116 :
117 0 : printf ("Please enter some text and press return.\n");
118 0 : printf ("Enter \"exit\" to stop and exit.\n");
119 :
120 : // Create glib main loop
121 0 : GMainContext * context = NULL; // use default context
122 0 : loop = g_main_loop_new (context, 0);
123 :
124 : // Initialize I/O binding tied to event loop
125 0 : binding = elektraIoGlibNew (context);
126 : // Read lines from STDIN
127 0 : input = elektraIoNewFdOperation (STDIN_FILENO, ELEKTRA_IO_READABLE, 1, readText, &lastInput);
128 : // Print last read data every second
129 0 : output = elektraIoNewTimerOperation (ONE_SECOND, 1, printText, &lastInput);
130 :
131 : // Add operations to binding
132 0 : elektraIoBindingAddFd (binding, input);
133 0 : elektraIoBindingAddTimer (binding, output);
134 :
135 : // Start the event loop
136 0 : g_main_loop_run (loop);
137 :
138 0 : g_main_loop_unref (loop);
139 :
140 : return 0;
141 : }
|