xmldaemon/main.cpp
changeset 359 e93ea158b423
equal deleted inserted replaced
358:f557be43b8c7 359:e93ea158b423
       
     1 /******************************************************************************
       
     2  *
       
     3  *  $Id$
       
     4  *
       
     5  *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
       
     6  *
       
     7  *  This file is part of the IgH EtherCAT Master.
       
     8  *
       
     9  *  The IgH EtherCAT Master is free software; you can redistribute it
       
    10  *  and/or modify it under the terms of the GNU General Public License
       
    11  *  as published by the Free Software Foundation; either version 2 of the
       
    12  *  License, or (at your option) any later version.
       
    13  *
       
    14  *  The IgH EtherCAT Master is distributed in the hope that it will be
       
    15  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    17  *  GNU General Public License for more details.
       
    18  *
       
    19  *  You should have received a copy of the GNU General Public License
       
    20  *  along with the IgH EtherCAT Master; if not, write to the Free Software
       
    21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    22  *
       
    23  *  The right to use EtherCAT Technology is granted and comes free of
       
    24  *  charge under condition of compatibility of product made by
       
    25  *  Licensee. People intending to distribute/sell products based on the
       
    26  *  code, have to sign an agreement to guarantee that products using
       
    27  *  software based on IgH EtherCAT master stay compatible with the actual
       
    28  *  EtherCAT specification (which are released themselves as an open
       
    29  *  standard) as the (only) precondition to have the right to use EtherCAT
       
    30  *  Technology, IP and trade marks.
       
    31  *
       
    32  *****************************************************************************/
       
    33 
       
    34 /**
       
    35    \file
       
    36    EtherCAT XML Daemon.
       
    37 */
       
    38 
       
    39 /*****************************************************************************/
       
    40 
       
    41 #include <signal.h>
       
    42 #include <sys/stat.h>
       
    43 #include <dirent.h>
       
    44 #include <syslog.h>
       
    45 
       
    46 #include <libxml/parser.h>
       
    47 
       
    48 #include <iostream>
       
    49 #include <list>
       
    50 using namespace std;
       
    51 
       
    52 #include "slave_device.hpp"
       
    53 
       
    54 /*****************************************************************************/
       
    55 
       
    56 unsigned int sig_int_term = 0;
       
    57 unsigned int sig_hangup = 0;
       
    58 string xml_dir;
       
    59 bool become_daemon = true;
       
    60 
       
    61 list<SlaveDevice> slaveDevices;
       
    62 
       
    63 /*****************************************************************************/
       
    64 
       
    65 void parse_xml_file(const char *);
       
    66 void parse_info(xmlDocPtr, xmlNodePtr);
       
    67 void parse_descriptions(xmlDocPtr, xmlNodePtr);
       
    68 void parse_devices(xmlDocPtr, xmlNodePtr);
       
    69 
       
    70 void read_xml_dir();
       
    71 void set_signal_handlers();
       
    72 void get_options(int, char *[]);
       
    73 void print_usage();
       
    74 void signal_handler(int);
       
    75 void init_daemon();
       
    76 
       
    77 /*****************************************************************************/
       
    78 
       
    79 int main(int argc, char *argv[])
       
    80 {
       
    81     set_signal_handlers();
       
    82     get_options(argc, argv);
       
    83 
       
    84     read_xml_dir();
       
    85 
       
    86     if (become_daemon) init_daemon();
       
    87 
       
    88     openlog("ecxmld", LOG_PID, LOG_DAEMON);
       
    89     syslog(LOG_INFO, "EtherCAT XML daemon starting up.");
       
    90 
       
    91     return 0;
       
    92 }
       
    93 
       
    94 /*****************************************************************************/
       
    95 
       
    96 void read_xml_dir()
       
    97 {
       
    98     DIR *dir;
       
    99     struct dirent *dir_ent;
       
   100     string entry;
       
   101 
       
   102     if (!(dir = opendir(xml_dir.c_str()))) {
       
   103         cerr << "ERROR: Failed to open XML directory \"" << xml_dir << "\"!"
       
   104              << endl;
       
   105         exit(1);
       
   106     }
       
   107 
       
   108     while ((dir_ent = readdir(dir))) {
       
   109         entry = dir_ent->d_name;
       
   110         if (entry.size() < 4
       
   111             || entry.substr(entry.size() - 4) != ".xml") continue;
       
   112 
       
   113         parse_xml_file((xml_dir + "/" + entry).c_str());
       
   114     }
       
   115 
       
   116     // Verzeichnis schliessen
       
   117     closedir(dir);
       
   118 }
       
   119 
       
   120 /*****************************************************************************/
       
   121 
       
   122 void parse_xml_file(const char *xml_file)
       
   123 {
       
   124     xmlDocPtr doc;
       
   125     xmlNodePtr cur;
       
   126 
       
   127     cout << xml_file << endl;
       
   128 
       
   129     if (!(doc = xmlParseFile(xml_file))) {
       
   130         cerr << "ERROR: Parse error in document!" << endl;
       
   131         return;
       
   132     }
       
   133 
       
   134     if (!(cur = xmlDocGetRootElement(doc))) {
       
   135         cout << "Empty document!" << endl;
       
   136         xmlFreeDoc(doc);
       
   137         return;
       
   138     }
       
   139 
       
   140     if (xmlStrcmp(cur->name, (const xmlChar *) "EtherCATInfo")) {
       
   141         cerr << "Document of the wrong type!" << endl;
       
   142         xmlFreeDoc(doc);
       
   143         return;
       
   144     }
       
   145 
       
   146     parse_info(doc, cur);
       
   147     xmlFreeDoc(doc);
       
   148 }
       
   149 
       
   150 /*****************************************************************************/
       
   151 
       
   152 void parse_info(xmlDocPtr doc, xmlNodePtr cur)
       
   153 {
       
   154     cout << "info" << endl;
       
   155     cur = cur->xmlChildrenNode;
       
   156 
       
   157     while (cur) {
       
   158         if ((!xmlStrcmp(cur->name, (const xmlChar *) "Descriptions"))) {
       
   159             parse_descriptions(doc, cur);
       
   160         }
       
   161 	cur = cur->next;
       
   162     }
       
   163 }
       
   164 
       
   165 /*****************************************************************************/
       
   166 
       
   167 void parse_descriptions(xmlDocPtr doc, xmlNodePtr cur)
       
   168 {
       
   169     cout << "desc" << endl;
       
   170     cur = cur->xmlChildrenNode;
       
   171 
       
   172     while (cur) {
       
   173         if ((!xmlStrcmp(cur->name, (const xmlChar *) "Devices"))) {
       
   174             parse_devices(doc, cur);
       
   175         }
       
   176 	cur = cur->next;
       
   177     }
       
   178 }
       
   179 
       
   180 /*****************************************************************************/
       
   181 
       
   182 void parse_devices(xmlDocPtr doc, xmlNodePtr cur)
       
   183 {
       
   184     cout << "devices" << endl;
       
   185     cur = cur->xmlChildrenNode;
       
   186 
       
   187     while (cur) {
       
   188         if ((!xmlStrcmp(cur->name, (const xmlChar *) "Device"))) {
       
   189             slaveDevices.push_back(SlaveDevice());
       
   190             slaveDevices.back().fromXml(doc, cur);
       
   191         }
       
   192 	cur = cur->next;
       
   193     }
       
   194 }
       
   195 
       
   196 /*****************************************************************************/
       
   197 
       
   198 void get_options(int argc, char *argv[])
       
   199 {
       
   200     int c;
       
   201 
       
   202     while (1) {
       
   203         if ((c = getopt(argc, argv, "d:kh")) == -1) break;
       
   204 
       
   205             switch (c) {
       
   206             case 'd':
       
   207                 xml_dir = optarg;
       
   208                 break;
       
   209 
       
   210             case 'k':
       
   211                 become_daemon = false;
       
   212                 break;
       
   213 
       
   214             case 'h':
       
   215                 print_usage();
       
   216                 exit(0);
       
   217 
       
   218             default:
       
   219                 print_usage();
       
   220                 exit(1);
       
   221         }
       
   222     }
       
   223 
       
   224     if (optind < argc) {
       
   225         cerr << "ERROR: Too many arguments!" << endl;
       
   226         print_usage();
       
   227         exit(1);
       
   228     }
       
   229 
       
   230     if (xml_dir == "") {
       
   231         cerr << "ERROR: XML directory not set!" << endl;
       
   232         print_usage();
       
   233         exit(1);
       
   234     }
       
   235 }
       
   236 
       
   237 /*****************************************************************************/
       
   238 
       
   239 void print_usage()
       
   240 {
       
   241     cout << "Usage: ecxmld [OPTIONS]" << endl
       
   242          << "   -d DIR   Set XML directory (MANDATORY)." << endl
       
   243          << "   -k       Do not detach from console." << endl
       
   244          << "   -h       Show this help." << endl;
       
   245 }
       
   246 
       
   247 /*****************************************************************************/
       
   248 
       
   249 void signal_handler(int sig)
       
   250 {
       
   251     if (sig == SIGHUP) {
       
   252         sig_hangup++;
       
   253     }
       
   254     else if (sig == SIGINT || sig == SIGTERM) {
       
   255         sig_int_term++;
       
   256     }
       
   257 }
       
   258 
       
   259 /*****************************************************************************/
       
   260 
       
   261 void set_signal_handlers()
       
   262 {
       
   263     struct sigaction action;
       
   264 
       
   265     action.sa_handler = signal_handler;
       
   266     sigemptyset(&action.sa_mask);
       
   267     action.sa_flags = 0;
       
   268 
       
   269     sigaction(SIGHUP, &action, 0);
       
   270     sigaction(SIGINT, &action, 0);
       
   271     sigaction(SIGTERM, &action, 0);
       
   272 }
       
   273 
       
   274 /*****************************************************************************/
       
   275 
       
   276 void init_daemon()
       
   277 {
       
   278     pid_t pid;
       
   279 
       
   280     if ((pid = fork()) < 0) {
       
   281         cerr << endl << "ERROR: fork() failed!" << endl << endl;
       
   282         exit(1);
       
   283     }
       
   284 
       
   285     if (pid) exit(0);
       
   286 
       
   287     if (setsid() == -1) {
       
   288         cerr << "ERROR: Failed to become session leader!" << endl;
       
   289         exit(1);
       
   290     }
       
   291 
       
   292     if (chdir("/") < 0) {
       
   293         cerr << "ERROR: Failed to change to file root!" << endl;
       
   294         exit(1);
       
   295     }
       
   296 
       
   297     umask(0);
       
   298 
       
   299     if (close(0) < 0) {
       
   300         cerr << "WARNING: Failed to close STDIN!" << endl;
       
   301     }
       
   302 
       
   303     if (close(1) < 0) {
       
   304         cerr << "WARNING: Failed to close STDOUT!" << endl;
       
   305     }
       
   306 
       
   307     if (close(2) < 0) {
       
   308         cerr << "WARNING: Failed to close STDERR!" << endl;
       
   309     }
       
   310 }
       
   311 
       
   312 /*****************************************************************************/