unix/linux/APIService.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.ibm.com/developerworks/oss/CPLv1.0.htm */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #endif
42 
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <sys/stat.h>
46 #include <sys/types.h>
47 #include <fcntl.h>
48 #include <signal.h>
49 #include <pwd.h>
50 #include "APIServer.hpp"
51 #include "stdio.h"
52 
53 // For testing purposes comment out the following line to force RXAPI to
54 // run as a foreground process.
55 #define RUN_AS_DAEMON
56 
57 #ifdef RUN_AS_DAEMON
58 //JLF tired to get ooRexx crash because root access needed to launch rxapi
59 //#define OOREXX_PIDFILE "/var/run/ooRexx.pid"
60 #define OOREXX_PIDFILE "/tmp/ooRexx.pid"
61 bool run_as_daemon = true;
62 #else
63 #define OOREXX_PIDFILE "/tmp/ooRexx.pid"
64 bool run_as_daemon = false;
65 #endif
66 
67 APIServer apiServer; // the real server instance
68 
69 
70 /*==========================================================================*
71  * Function: Run
72  *
73  * Purpose:
74  *
75  * handles the original RXAPI functions.
76  * Perform the message loop
77  *
78  *
79  *==========================================================================*/
80 void Run (bool asService)
81 {
82  try
83  {
84  apiServer.initServer(); // start up the server
85  apiServer.listenForConnections(); // go into the message loop
86  }
87  catch (ServiceException *)
88  {
89  }
90  apiServer.terminateServer(); // shut everything down
91 }
92 
93 /*==========================================================================*
94  * Function: Stop
95  *
96  * Purpose:
97  *
98  * handles the stop request.
99  *
100  *
101  *==========================================================================*/
102 void Stop(int signo)
103 {
104  apiServer.terminateServer(); // shut everything down
105 
106  exit(1);
107 }
108 
109 /////////////////////////////////////////////////////////////////
110 /////////////////////////////////////////////////////////////////
111 // Routines to run RXAPI as an daemon BEGIN
112 
113 
114 /*==========================================================================*
115  * Function: morph2daemon
116  *
117  * Purpose:
118  *
119  * Turn this process into a daemon.
120  *
121  * Returns TRUE if a daemon, FALSE if not or an error
122  *
123  *==========================================================================*/
124 static bool morph2daemon(void)
125 {
126  char pid_buf[256];
127 
128  if (run_as_daemon == false) {
129  return true; // go ahead and run in the foreground
130  }
131 
132  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
133  return false;
134  }
135 
136  pid_t pid = fork();
137  if (pid < 0) {
138  return false;
139  }
140  // if we are the parent process then we are done
141  if (pid != 0) {
142  exit( 0 );
143  }
144 
145  // become the session leader
146  setsid();
147  // second fork to become a real daemon
148  pid = fork();
149  if (pid < 0) {
150  return false;
151  }
152  // if we are the parent process then we are done
153  if (pid != 0) {
154  exit(0);
155  }
156 
157  // create the pid file (overwrite of old pid file is ok)
158  unlink(OOREXX_PIDFILE);
159  int pfile = open(OOREXX_PIDFILE, O_WRONLY | O_CREAT, 0640);
160  snprintf(pid_buf, sizeof(pid_buf), "%d\n", (int)getpid());
161  ssize_t writeResult = write(pfile, pid_buf, strlen(pid_buf));
162  close(pfile);
163 
164  // housekeeping
165  int chdirResult = chdir("/");
166  umask(0);
167  for(int i = 0; i < 1024; i++) {
168  close(i);
169  }
170 
171  return true;
172 }
173 
174 
175 /*==========================================================================*
176  * Function: main
177  *
178  * Purpose:
179  *
180  * Main entry point.
181  *
182  *==========================================================================*/
183 int main(int argc, char *argv[])
184 {
185  char pid_buf[256];
186  int pfile, len;
187  pid_t pid = 0;
188  struct sigaction sa;
189  // Get the command line args
190  if (argc > 1) {
191  printf("Error: Invalid command line option(s).\n");
192  printf(" Aborting execution.\n\n");
193  return -1;
194  }
195 
196  // see if we are already running
197  if ((pfile = open(OOREXX_PIDFILE, O_RDONLY)) > 0) {
198  len = read(pfile, pid_buf, sizeof(pid_buf) - 1);
199  close(pfile);
200  pid_buf[len] = '\0';
201  pid = (pid_t)atoi(pid_buf);
202  if (pid && (pid == getpid() || kill(pid, 0) < 0)) {
203  unlink(OOREXX_PIDFILE);
204  } else {
205  // there is already a server running
206  printf("Error: There is already a server running.\n");
207  printf(" Aborting execution.\n");
208  return -1;
209  }
210  }
211 
212  // write the pid file
213  pfile = open(OOREXX_PIDFILE, O_WRONLY | O_CREAT,
214  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
215  if (pfile == -1) {
216  // cannot open pid file
217  printf("Error: Cannot open PID file %s.\n", OOREXX_PIDFILE);
218  printf(" Aborting execution.\n\n");
219  return -1;
220  }
221  snprintf(pid_buf, sizeof(pid_buf), "%d\n", (int)getpid());
222  ssize_t r = write(pfile, pid_buf, strlen(pid_buf));
223  close(pfile);
224 
225  // make ourselves a daemon
226  // - if this is AIX we check if the rxapi daemon was sarted via SRC
227  // - if the daemon was started via SRC we do not morph - the SRC handles this
228  //
229  // - add to AIX SRC without auto restart:
230  // mkssys -s rxapi -p /opt/ooRexx/bin/rxapi -i /dev/null -e /dev/console \
231  // -o /dev/console -u 0 -S -n 15 -f 9 -O -Q
232  //
233  // - add to AIX SRC with auto restart:
234  // mkssys -s rxapi -p /opt/ooRexx/bin/rxapi -i /dev/null -e /dev/console \
235  // -o /dev/console -u 0 -S -n 15 -f 9 -R -Q
236  if (morph2daemon() == false) {
237  return -1;
238  }
239 
240  // run the server
241  if (run_as_daemon == false) {
242  printf("Starting request processing loop.\n");
243  }
244 
245  // handle kill -15
246  (void) sigemptyset(&sa.sa_mask);
247  (void) sigaddset(&sa.sa_mask, SIGTERM);
248  sa.sa_flags = SA_RESTART;
249  sa.sa_handler = Stop;
250  if (sigaction(SIGTERM, &sa, NULL) == -1) {
251  exit(1);
252  }
253 
254  Run(false);
255 
256  return 0;
257 }
258 
void initServer()
Definition: APIServer.cpp:53
void terminateServer()
Definition: APIServer.cpp:69
void listenForConnections()
Definition: APIServer.cpp:82
static bool morph2daemon(void)
int main(int argc, char *argv[])
void Stop(int signo)
void Run(bool asService)
#define OOREXX_PIDFILE
bool run_as_daemon
APIServer apiServer
SSIZE_T ssize_t