Sat, 08 Dec 2018 15:01:23 +0100
Added a loader during recipe load. Recalculate percentages if a fermentable row is deleted. Don't edit amounts if using weight percentages. Update grid percentages if a fermentable amount is changed. Recalculate IBU's after changes with fermentables.
0 | 1 | /***************************************************************************** |
2 | * Copyright (C) 2017-2018 | |
3 | * | |
4 | * Michiel Broek <mbroek at mbse dot eu> | |
5 | * | |
6 | * This file is part of the bms (Brewery Management System) | |
7 | * | |
8 | * This is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2, or (at your option) any | |
11 | * later version. | |
12 | * | |
13 | * bms is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with ThermFerm; see the file COPYING. If not, write to the Free | |
20 | * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | |
21 | *****************************************************************************/ | |
22 | ||
23 | #include "bms.h" | |
24 | #include "xutil.h" | |
25 | #include "rdconfig.h" | |
26 | #include "lock.h" | |
27 | #include "mqtt.h" | |
28 | #include "mysql.h" | |
29 | ||
30 | ||
31 | int my_shutdown = FALSE; | |
32 | int debug = FALSE; | |
33 | static pid_t pgrp, mypid; | |
34 | char *Private_Path = NULL; /* Users data path */ | |
35 | //char *resource_path = NULL; /* Webserver root */ | |
36 | ||
37 | //extern struct lws_context *context; | |
38 | ||
39 | ||
40 | void help(void) | |
41 | { | |
42 | fprintf(stdout, "bmsd v%s starting\n\n", VERSION); | |
43 | fprintf(stdout, "Usage: bmsd [-d] [-h]\n"); | |
44 | fprintf(stdout, " -d --debug Debug and run in foreground\n"); | |
45 | fprintf(stdout, " -h --help Display this help\n"); | |
46 | } | |
47 | ||
48 | ||
49 | ||
50 | void die(int onsig) | |
51 | { | |
52 | switch (onsig) { | |
53 | case SIGHUP: syslog(LOG_NOTICE, "Got SIGHUP, shutting down"); | |
54 | break; | |
55 | case SIGINT: syslog(LOG_NOTICE, "Keyboard interrupt, shutting down"); | |
56 | break; | |
57 | case SIGTERM: syslog(LOG_NOTICE, "Got SIGTERM, shutting down"); | |
58 | break; | |
59 | case SIGSEGV: syslog(LOG_NOTICE, "Got SIGSEGV, shutting down"); | |
60 | my_shutdown = TRUE; | |
61 | exit(SIGSEGV); | |
62 | break; | |
63 | default: syslog(LOG_NOTICE, "die() on signal %d", onsig); | |
64 | } | |
65 | my_shutdown = TRUE; | |
66 | } | |
67 | ||
68 | ||
69 | ||
70 | int server(void) { | |
71 | uid_t myuid; | |
72 | struct passwd *mypwd; | |
73 | int rc = 0; | |
74 | ||
75 | myuid = getuid(); | |
76 | mypwd = getpwuid(myuid); | |
77 | if (mypwd == NULL) { | |
78 | fprintf(stderr, "[main] Could not find passwd entry\n"); | |
79 | return 1; | |
80 | } | |
81 | ||
82 | Private_Path = xstrcpy(mypwd->pw_dir); | |
83 | Private_Path = xstrcat(Private_Path, (char *)"/.bms"); | |
84 | ||
85 | if (lockprog((char *)"bmsd")) { | |
86 | syslog(LOG_NOTICE, "Can't lock"); | |
87 | return 1; | |
88 | } | |
89 | ||
90 | if (rdconfig()) { | |
91 | rc = 2; | |
92 | goto endit1; | |
93 | } | |
94 | ||
95 | if (bms_mysql_init()) { | |
96 | rc = 3; | |
97 | goto endit1; | |
98 | } | |
99 | if (mqtt_connect()) { | |
100 | rc = 4; | |
101 | goto endit2; | |
102 | } | |
103 | ||
104 | if (debug) | |
105 | fprintf(stdout, "[main] Entering main loop\n"); | |
106 | ||
107 | while (my_shutdown == FALSE) { | |
108 | ||
109 | usleep(100000); | |
110 | } | |
111 | if (debug) | |
112 | fprintf(stdout, "[main] Exit from main loop\n"); | |
113 | ||
114 | /* | |
115 | * Remove our topics and close MQTT connection. | |
116 | */ | |
117 | mqtt_disconnect(); | |
118 | ||
119 | endit2: | |
120 | bms_mysql_end(); | |
121 | ||
122 | endit1: | |
123 | ||
124 | killconfig(); | |
125 | ||
126 | ulockprog((char *)"bmsd"); | |
127 | ||
128 | free(Private_Path); | |
129 | Private_Path = NULL; | |
130 | ||
131 | if (debug) | |
132 | fprintf(stdout, "[main] Server shutdown complete\n"); | |
133 | return rc; | |
134 | } | |
135 | ||
136 | ||
137 | ||
138 | int main(int argc, char *argv[]) { | |
139 | int rc, c, i; | |
140 | pid_t frk; | |
141 | ||
142 | while (1) { | |
143 | int option_index = 0; | |
144 | static struct option long_options[] = { | |
145 | {"debug", 0, 0, 'c'}, | |
146 | {"help", 0, 0, 'h'}, | |
147 | {0, 0, 0, 0} | |
148 | }; | |
149 | ||
150 | c = getopt_long(argc, argv, "dh", long_options, &option_index); | |
151 | if (c == -1) | |
152 | break; | |
153 | switch (c) { | |
154 | case 'd': debug = TRUE; | |
155 | break; | |
156 | case 'h': help(); | |
157 | return 1; | |
158 | } | |
159 | } | |
160 | ||
161 | openlog("bmsd", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_USER); | |
162 | syslog(LOG_NOTICE, "bmsd v%s starting", VERSION); | |
163 | if (debug) | |
164 | fprintf(stdout, "bmsd v%s starting\n", VERSION); | |
165 | ||
166 | ||
167 | /* | |
168 | * Catch all the signals we can, and ignore the rest. Note that SIGKILL can't be ignored | |
169 | * but that's live. This daemon should only be stopped by SIGTERM. | |
170 | * Don't catch SIGCHLD. | |
171 | */ | |
172 | for (i = 0; i < NSIG; i++) { | |
173 | if ((i != SIGCHLD) && (i != SIGKILL) && (i != SIGSTOP)) | |
174 | signal(i, (void (*))die); | |
175 | } | |
176 | ||
177 | if (debug) { | |
178 | /* | |
179 | * For debugging run in foreground. | |
180 | */ | |
181 | rc = server(); | |
182 | } else { | |
183 | /* | |
184 | * Server initialization is complete. Now we can fork the | |
185 | * daemon and return to the user. We need to do a setpgrp | |
186 | * so that the daemon will no longer be assosiated with the | |
187 | * users control terminal. This is done before the fork, so | |
188 | * that the child will not be a process group leader. Otherwise, | |
189 | * if the child were to open a terminal, it would become | |
190 | * associated with that terminal as its control terminal. | |
191 | */ | |
192 | if ((pgrp = setpgid(0, 0)) == -1) { | |
193 | syslog(LOG_NOTICE, "setpgpid failed"); | |
194 | } | |
195 | ||
196 | frk = fork(); | |
197 | switch (frk) { | |
198 | case -1: | |
199 | syslog(LOG_NOTICE, "Daemon fork failed: %s", strerror(errno)); | |
200 | exit(1); | |
201 | case 0: /* | |
202 | * Run the daemon | |
203 | */ | |
204 | fclose(stdin); | |
205 | if (open("/dev/null", O_RDONLY) != 0) { | |
206 | syslog(LOG_NOTICE, "Reopen of stdin to /dev/null failed"); | |
207 | _exit(2); | |
208 | } | |
209 | fclose(stdout); | |
210 | if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 1) { | |
211 | syslog(LOG_NOTICE, "Reopen of stdout to /dev/null failed"); | |
212 | _exit(2); | |
213 | } | |
214 | fclose(stderr); | |
215 | if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 2) { | |
216 | syslog(LOG_NOTICE, "Reopen of stderr to /dev/null failed"); | |
217 | _exit(2); | |
218 | } | |
219 | mypid = getpid(); | |
220 | rc = server(); | |
221 | break; | |
222 | /* Not reached */ | |
223 | default: | |
224 | /* | |
225 | * Here we detach this process and let the child | |
226 | * run the deamon process. | |
227 | */ | |
228 | syslog(LOG_NOTICE, "Starting daemon with pid %d", frk); | |
229 | exit(0); | |
230 | } | |
231 | } | |
232 | ||
233 | syslog(LOG_NOTICE, "Finished, rc=%d", rc); | |
234 | return rc; | |
235 | } | |
236 | ||
237 |