]> git.ipfire.org Git - people/ms/pakfire.git/blob - src/cli/lib/daemon.c
cli: daemon: Build more scaffolding
[people/ms/pakfire.git] / src / cli / lib / daemon.c
1 /*#############################################################################
2 # #
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2023 Pakfire development team #
5 # #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
18 # #
19 #############################################################################*/
20
21 #include <errno.h>
22 #include <sys/epoll.h>
23
24 #include <pakfire/ctx.h>
25 #include <pakfire/httpclient.h>
26 #include <pakfire/logging.h>
27
28 #include "daemon.h"
29
30 #define EPOLL_MAX_EVENTS 8
31
32 struct cli_daemon_ctx {
33 struct pakfire_ctx* ctx;
34 };
35
36 static int cli_daemon_loop(struct pakfire_ctx* ctx) {
37 struct pakfire_httpclient* httpclient = NULL;
38 struct epoll_event events[EPOLL_MAX_EVENTS];
39 struct epoll_event event;
40 int epollfd = -1;
41 int num = 0;
42 int fd = -1;
43 int e;
44 int r;
45
46 // Setup the HTTP client
47 r = pakfire_httpclient_create(&httpclient, ctx);
48 if (r)
49 goto ERROR;
50
51 // Setup epoll()
52 epollfd = epoll_create1(EPOLL_CLOEXEC);
53 if (epollfd < 0) {
54 CTX_ERROR(ctx, "Could not setup main loop: %s\n", strerror(errno));
55 r = -errno;
56 goto ERROR;
57 }
58
59 CTX_DEBUG(ctx, "Entering main loop...\n");
60
61 // Main loop, loop, loop, looooop....
62 for (;;) {
63 num = epoll_wait(epollfd, events, EPOLL_MAX_EVENTS, -1);
64 if (num < 1) {
65 switch (errno) {
66 case EINTR:
67 break;
68
69 default:
70 CTX_ERROR(ctx, "epoll_wait() failed: %m\n");
71 r = -errno;
72 break;
73 }
74 goto ERROR;
75 }
76
77 // Handle all events
78 for (int i = 0; i < num; i++) {
79 fd = events[i].data.fd;
80 e = events[i].events;
81
82 // XXX Do the work...
83
84 // Remove the file descriptor if it has been closed
85 if (e & EPOLLHUP) {
86 r = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL);
87 if (r) {
88 CTX_ERROR(ctx, "Could not remove closed fd %d: %s\n", fd, strerror(errno));
89 r = -errno;
90 goto ERROR;
91 }
92 }
93 }
94 }
95
96 ERROR:
97 CTX_DEBUG(ctx, "Exited main loop...\n");
98
99 if (httpclient)
100 pakfire_httpclient_unref(httpclient);
101 if (epollfd >= 0)
102 close(epollfd);
103
104 return r;
105 }
106
107 int cli_daemon_main(struct pakfire_ctx* ctx) {
108 int r;
109
110 CTX_INFO(ctx, "Pakfire Daemon has been successfully initialized\n");
111
112 // Run the main loop
113 r = cli_daemon_loop(ctx);
114 if (r)
115 goto ERROR;
116
117 ERROR:
118 return r;
119 }