plptools
Loading...
Searching...
No Matches
main.cc
Go to the documentation of this file.
1/*
2 * This file is part of plptools.
3 *
4 * Copyright (C) 1999 Philip Proudman <philip.proudman@btinternet.com>
5 * Copyright (C) 1999-2001 Fritz Elfert <felfert@to.com>
6 * Copyright (C) 2026 Jason Morley <hello@jbmorley.co.uk>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * along with this program; if not, see <https://www.gnu.org/licenses/>.
20 *
21 */
22#include "config.h"
23
24#include <string>
25#include <cstring>
26#include <iostream>
27
28#include <cliutils.h>
29#include <bufferstore.h>
30#include <tcpsocket.h>
31#include <iowatch.h>
32#include <log.h>
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <signal.h>
37#include <errno.h>
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <pthread.h>
42#include <plpintl.h>
43#include <unistd.h>
44
45#include "ignore-value.h"
46
47#include "ncp_log.h"
48#include "ncpsession.h"
49#include "datalink.h"
50
51#ifndef _GNU_SOURCE
52#define _GNU_SOURCE
53#endif
54#include <getopt.h>
55
56using namespace std;
57
58// Global session state specific to the `ncpd` process. This exists as a global solely for the purpose of accessing it
59// from the interrupt handlers.
61
62static void
64{
65 linf << _("Got SIGTERM") << endl;
67 signal(SIGTERM, term_handler);
68};
69
70static void
72{
73 linf << _("Got SIGINT") << endl;
75 signal(SIGINT, int_handler);
76};
77
78static void
80{
81 cout << _(
82 "Usage: ncpd [OPTIONS]...\n"
83 "\n"
84 "Supported options:\n"
85 "\n"
86 " -d, --dontfork Run in foreground, don't fork\n"
87 " -h, --help Display this text.\n"
88 " -V, --version Print version and exit.\n"
89 " -e, --autoexit Exit after device is disconnected.\n"
90 " -v, --verbose=LOGCLASS Enable logging of LOGCLASS events\n"
91 " Valid log classes are:\n"
92 " m - main program\n"
93 " nl - NCP protocol log\n"
94 " nd - NCP protocol data dump\n"
95 " ll - PLP protocol log\n"
96 " ld - PLP protocol data dump\n"
97 " pl - physical I/O log\n"
98 " ph - physical I/O handshake\n"
99 " pd - physical I/O data dump\n"
100 " all - All of the above\n"
101 " -n, --nodsr Disable DSR check. Use this when DSR detection is\n"
102 " poorly implemented in RS232 drivers or hardware.\n"
103 " WARNING: Could cause connection instability.\n"
104 " -s, --serial=DEV Use serial device DEV.\n"
105 " -b, --baudrate=RATE Set serial speed to BAUD.\n"
106 );
107 cout <<
108#if DSPEED > 0
109#define SPEEDSTR(x) #x
110 _(" Default: ") << DSPEED << "\n";
111#else
112 _(" Default: Autocycle 115200, 57600, 38400, 19200, 9600\n");
113#endif
114 cout << _(
115 " -p, --port=[HOST:]PORT Listen on host HOST, port PORT.\n"
116 " Default for HOST: 127.0.0.1\n"
117 " Default for PORT: "
118 ) << DPORT << "\n\n";
119}
120
121static void
123 cerr << _("Try `ncpd --help' for more information") << endl;
124}
125
126static struct option opts[] = {
127 {"dontfork", no_argument, 0, 'd'},
128 {"autoexit", no_argument, 0, 'e'},
129 {"help", no_argument, 0, 'h'},
130 {"version", no_argument, 0, 'V'},
131 {"verbose", required_argument, 0, 'v'},
132 {"port", required_argument, 0, 'p'},
133 {"serial", required_argument, 0, 's'},
134 {"baudrate", required_argument, 0, 'b'},
135 {"nodsr", no_argument, 0, 'n'},
136 {NULL, 0, 0, 0 }
137};
138
139int
140main(int argc, char **argv)
141{
142 int pid;
143 bool dofork = true;
144
145 int sockNum = cli_utils::lookup_default_port();
146 int baudRate = DSPEED;
147 string host = "127.0.0.1";
148 const char *serialDevice = NULL;
149 unsigned short nverbose = 0;
150 bool autoexit = false;
151 bool noDSRCheck = false;
152
156
157 while (1) {
158 int c = getopt_long(argc, argv, "hdeVb:s:p:v:n", opts, NULL);
159 if (c == -1)
160 break;
161 switch (c) {
162 case '?':
163 usage();
164 return -1;
165 case 'V':
166 cout << _("ncpd Version ") << VERSION << endl;
167 return 0;
168 case 'h':
169 help();
170 return 0;
171 case 'v':
172 if (!strcmp(optarg, "nl"))
173 nverbose |= NCP_DEBUG_LOG;
174 if (!strcmp(optarg, "nd"))
175 nverbose |= NCP_DEBUG_DUMP;
176 if (!strcmp(optarg, "ll"))
177 nverbose |= LNK_DEBUG_LOG;
178 if (!strcmp(optarg, "ld"))
179 nverbose |= LNK_DEBUG_DUMP;
180 if (!strcmp(optarg, "pl"))
181 nverbose |= PKT_DEBUG_LOG;
182 if (!strcmp(optarg, "pd"))
183 nverbose |= PKT_DEBUG_DUMP;
184 if (!strcmp(optarg, "ph"))
185 nverbose |= PKT_DEBUG_HANDSHAKE;
186 if (!strcmp(optarg, "m"))
187 nverbose |= NCP_SESSION_LOG;
188 if (!strcmp(optarg, "all")) {
189 nverbose = NCP_DEBUG_LOG | NCP_DEBUG_DUMP |
193 }
194 break;
195 case 'd':
196 dofork = 0;
197 break;
198 case 'e':
199 autoexit = true;
200 break;
201 case 'b':
202 if (!strcmp(optarg, "auto"))
203 baudRate = -1;
204 else
205 baudRate = atoi(optarg);
206 break;
207 case 's':
208 serialDevice = optarg;
209 break;
210 case 'p':
211 if (!cli_utils::parse_port(optarg, &host, &sockNum)) {
212 cout << _("Invalid port definition.") << endl;
213 return 1;
214 }
215 break;
216 case 'n':
217 noDSRCheck = true;
218 linf << "DSR check disabled" << endl;
219 break;
220 }
221 }
222 if (optind < argc) {
223 usage();
224 return -1;
225 }
226
227 if (serialDevice == NULL)
228 serialDevice = DDEV;
229
230 if (dofork)
231 pid = fork();
232 else
233 pid = 0;
234 switch (pid) {
235 case 0:
236 {
237 signal(SIGTERM, term_handler);
238 signal(SIGINT, int_handler);
239
240 // Configure the daemon process before starting up.
241 if (dofork) {
242 openlog("ncpd", LOG_CONS|LOG_PID, LOG_DAEMON);
243 dlog.useSyslog();
244 elog.useSyslog();
245 ilog.useSyslog();
246 setsid();
247 ignore_value(chdir("/"));
248 int devnull = open("/dev/null", O_RDWR, 0);
249 if (devnull != -1) {
250 dup2(devnull, STDIN_FILENO);
251 dup2(devnull, STDOUT_FILENO);
252 dup2(devnull, STDERR_FILENO);
253 if (devnull > 2) {
254 close(devnull);
255 }
256 }
257 }
258
259 // Once our process is fully set up, we can create and start the session.
260 sharedSession = new NCPSession(sockNum,
261 baudRate,
262 host,
263 serialDevice,
264 autoexit,
265 noDSRCheck,
266 nverbose);
269 delete sharedSession;
270
271 break;
272 }
273 case -1:
274 lerr << "fork: " << strerror(errno) << endl;
275 break;
276 default:
277 exit(0);
278 }
279 linf << _("normal exit") << endl;
280 return 0;
281}
Responsible for orchestrating the high-level life cycle of a daemon-side NCP server and multiplexing ...
Definition: ncpsession.h:42
void cancel()
Mark the session as cancelled.
Definition: ncpsession.cc:235
void wait()
Wait for the session to terminate.
Definition: ncpsession.cc:251
int start()
Creates and manages all the threads necessary to run a full session for communicating with a Psion an...
Definition: ncpsession.cc:225
void useFileDescriptor()
Write logs to the file descriptor passed in the constructor.
Definition: log.h:76
void useSyslog()
Write logs using syslog.
Definition: log.h:68
bool parse_port(const std::string &arg, std::string *host, int *port)
Definition: cliutils.cc:53
int lookup_default_port()
Definition: cliutils.cc:44
Definition: doctest.h:522
logbuf dlog(LOG_DEBUG, STDOUT_FILENO)
Definition: ncp_log.cc:35
logbuf elog(LOG_ERR, STDERR_FILENO)
Definition: ncp_log.cc:36
logbuf ilog(LOG_INFO, STDOUT_FILENO)
Definition: ncp_log.cc:34
#define NCP_DEBUG_DUMP
Definition: ncp_log.h:29
#define PKT_DEBUG_HANDSHAKE
Definition: ncp_log.h:34
std::ostream lerr
#define LNK_DEBUG_LOG
Definition: ncp_log.h:30
#define PKT_DEBUG_DUMP
Definition: ncp_log.h:33
#define NCP_SESSION_LOG
Definition: ncp_log.h:35
#define PKT_DEBUG_LOG
Definition: ncp_log.h:32
#define LNK_DEBUG_DUMP
Definition: ncp_log.h:31
#define NCP_DEBUG_LOG
Definition: ncp_log.h:28
std::ostream linf
static void term_handler(int)
Definition: main.cc:63
static void int_handler(int)
Definition: main.cc:71
int main(int argc, char **argv)
Definition: main.cc:140
static void usage()
Definition: main.cc:122
static struct option opts[]
Definition: main.cc:126
static NCPSession * sharedSession
Definition: main.cc:60
static void help()
Definition: main.cc:79
#define _(String)
Definition: plpintl.h:34