Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Example program for io_uv 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/uv.h> // I/O binding constructor for uv (elektraIoUvNew)
30 :
31 : #include <uv.h> // uv functions
32 :
33 : #define BUFFER_LENGTH 255
34 : #define ONE_SECOND 1000
35 :
36 : ElektraIoInterface * binding;
37 : ElektraIoFdOperation * input;
38 : ElektraIoTimerOperation * output;
39 :
40 0 : int min (int a, int b)
41 : {
42 0 : return (a > b) ? b : a;
43 : }
44 :
45 0 : void stopLoop (void)
46 : {
47 : // Cleanup
48 0 : elektraIoBindingRemoveFd (input);
49 0 : elektraIoBindingRemoveTimer (output);
50 0 : elektraFree (input);
51 0 : elektraFree (output);
52 0 : elektraIoBindingCleanup (binding);
53 :
54 0 : uv_stop (uv_default_loop ());
55 0 : }
56 :
57 0 : void readText (ElektraIoFdOperation * fdOp, int flags ELEKTRA_UNUSED)
58 : {
59 0 : printf ("input: file descriptor became readable\n");
60 :
61 0 : char * lastInput = elektraIoFdGetData (fdOp);
62 0 : ELEKTRA_NOT_NULL (lastInput);
63 :
64 : char buffer[BUFFER_LENGTH];
65 0 : int bytesRead = read (elektraIoFdGetFd (fdOp), &buffer, BUFFER_LENGTH);
66 0 : if (bytesRead != -1)
67 : {
68 : // make sure there is a null terminator in buffer
69 0 : buffer[min (BUFFER_LENGTH - 1, bytesRead + 1)] = 0;
70 : // remove newline from string
71 0 : buffer[strcspn (buffer, "\r\n")] = 0;
72 : // copy to lastInput
73 0 : memcpy (lastInput, buffer, BUFFER_LENGTH);
74 : }
75 : else
76 : {
77 0 : int error = errno;
78 0 : if (error != EINTR)
79 : {
80 0 : printf ("input: I/O error occurred - exiting\n");
81 0 : stopLoop ();
82 : }
83 : }
84 0 : }
85 :
86 0 : void printText (ElektraIoTimerOperation * timerOp)
87 : {
88 0 : char * lastInput = elektraIoTimerGetData (timerOp);
89 0 : ELEKTRA_NOT_NULL (lastInput);
90 :
91 0 : if (strcmp (lastInput, "exit") == 0)
92 : {
93 0 : printf ("timer: stopping\n");
94 0 : stopLoop ();
95 : }
96 : else
97 : {
98 0 : if (strlen (lastInput) > 0)
99 : {
100 0 : printf ("timer: last text was \"%s\"\n", lastInput);
101 : }
102 : else
103 : {
104 0 : printf ("timer: text is empty\n");
105 : }
106 : }
107 0 : }
108 :
109 0 : int main (void)
110 : {
111 : // Initialize buffer
112 : char lastInput[BUFFER_LENGTH];
113 0 : memset (lastInput, 0, BUFFER_LENGTH);
114 :
115 0 : printf ("Please enter some text and press return.\n");
116 0 : printf ("Enter \"exit\" to stop and exit.\n");
117 :
118 : // Create libuv event loop
119 0 : uv_loop_t * loop = uv_default_loop ();
120 :
121 : // Initialize I/O binding tied to event loop
122 0 : binding = elektraIoUvNew (loop);
123 : // Read lines from STDIN
124 0 : input = elektraIoNewFdOperation (STDIN_FILENO, ELEKTRA_IO_READABLE, 1, readText, &lastInput);
125 : // Print last read data every second
126 0 : output = elektraIoNewTimerOperation (ONE_SECOND, 1, printText, &lastInput);
127 :
128 : // Add operations to binding
129 0 : elektraIoBindingAddFd (binding, input);
130 0 : elektraIoBindingAddTimer (binding, output);
131 :
132 : // Start the event loop
133 0 : uv_run (loop, UV_RUN_DEFAULT);
134 :
135 : #ifdef HAVE_LIBUV1
136 0 : uv_loop_close (loop);
137 : #elif HAVE_LIBUV0
138 : uv_loop_delete (loop);
139 : #endif
140 :
141 : return 0;
142 : }
|