File: dibbler-client.cpp

package info (click to toggle)
dibbler 1.0.1-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 13,352 kB
  • sloc: cpp: 60,323; ansic: 12,235; sh: 11,951; yacc: 3,418; lex: 969; makefile: 940; perl: 319; xml: 116; python: 74
file content (208 lines) | stat: -rw-r--r-- 5,280 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/*
 * Dibbler - a portable DHCPv6
 *
 * authors: Tomasz Mrugalski <thomson@klub.com.pl>
 *
 * released under GNU GPL v2 only licence
 *
 */

#include <signal.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "DHCPClient.h"
#include "Portable.h"
#include "Logger.h"
#include "daemon.h"
#include "ClntCfgMgr.h"
#include <map>
#include <pthread.h>

using namespace std;

#define IF_RECONNECTED_DETECTED -1

extern pthread_mutex_t lock;

TDHCPClient* ptr = 0;

std::string WORKDIR(DEFAULT_WORKDIR);
std::string CLNTCONF_FILE(DEFAULT_CLNTCONF_FILE);
std::string CLNTLOG_FILE(DEFAULT_CLNTLOG_FILE);
std::string CLNTPID_FILE(DEFAULT_CLNTPID_FILE);

void signal_handler(int n) {
    Log(Crit) << "Signal received. Shutting down." << LogEnd;
    ptr->stop();
}


#ifdef MOD_CLNT_CONFIRM
void signal_handler_of_linkstate_change(int n) {
    Log(Notice) << "Network switch off event detected. initiating CONFIRM." << LogEnd;
    pthread_mutex_lock(&lock);
    pthread_mutex_unlock(&lock);
}
#endif

int status() {

    pid_t pid = getServerPID();
    if (pid==-1) {
	cout << "Dibbler server: NOT RUNNING." << endl;
    } else {
	cout << "Dibbler server: RUNNING, pid=" << pid << endl;
    }
    
    pid = getClientPID();
    if (pid==-1) {
	cout << "Dibbler client: NOT RUNNING." << endl;
    } else {
	cout << "Dibbler client: RUNNING, pid=" << pid << endl;
    }
    int result = (pid > 0)? 0: -1;

    pid = getRelayPID();
    if (pid==-1) {
	cout << "Dibbler relay : NOT RUNNING." << endl;
    } else {
	cout << "Dibbler relay : RUNNING, pid=" << pid << endl;
    }

    return result;
}

int run() {
    if (!init(CLNTPID_FILE.c_str(), WORKDIR.c_str())) {
	die(CLNTPID_FILE.c_str());
	return -1;
    }

    // Change attribs to the client file: 644 (user=rw, group=r, other=r)
    chmod(CLNTPID_FILE.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

    if (lowlevelInit()<0) {
	cout << "Lowlevel init failed:" << error_message() << endl;
	die(CLNTPID_FILE.c_str());
	return -1;
    }

    TDHCPClient client(CLNTCONF_FILE.c_str());
    ptr = &client;

    if (ptr->isDone()) {
	die(CLNTPID_FILE.c_str());
	return -1;
    }

    // connect signals (SIGTERM, SIGINT = shutdown)
    signal(SIGTERM, signal_handler);
    signal(SIGINT, signal_handler);

#ifdef MOD_CLNT_CONFIRM
    // CHANGED: add a signal handling function to handle SIGUSR1,
    // which will be generated if network switch off.
    // SIGUSR1 = link state-change
    signal(SIGUSR1, signal_handler_of_linkstate_change);
    Log(Notice) << "CONFIRM support compiled in." << LogEnd;
#else
    Log(Info) << "CONFIRM support not compiled in." << LogEnd;
#endif

    ptr->run();

    lowlevelExit();

    die(CLNTPID_FILE.c_str());

    return 0;
}

int help() {
    cout << "Usage:" << endl;
    cout << " dibbler-client ACTION [OPTION]" << endl
	 << " ACTION = status|start|stop|install|uninstall|run" << endl
	 << " status    - show status and exit" << endl
	 << " start     - start installed service" << endl
	 << " stop      - stop installed service" << endl
	 << " install   - Not available in Linux/Unix systems." << endl
	 << " uninstall - Not available in Linux/Unix systems." << endl
	 << " run       - run in the console" << endl
	 << " help      - displays usage info." << endl
         << endl
         << " OPTION = -w <directory>" << endl
         << " -w <directory> - specify the client's working directory." << endl;
    return 0;
}

int main(int argc, char * argv[])
{
    int result = -1;

    // If at least one parameter (command) is not specified, then...
    if (argc < 2) {
        help();
        return EXIT_FAILURE;
    }

    // The first parameter is command
    const char* command = argv[1];

    // Let's parse additional commands if specified
    if (argc > 2) {
        int c;

        // Let's go through any additional command line options.
        while ((c = getopt(argc-1, argv + 1, "w:")) != -1) {
            switch (c)
            {
            case 'w':
                WORKDIR = string(optarg);
                CLNTPID_FILE = string(optarg) + "/client.pid";
                CLNTCONF_FILE = string(optarg) + "/client.conf";
                CLNTLOG_FILE = string(optarg) + "/client.log";
                break;
            default:
                help();
                return result ? EXIT_FAILURE: EXIT_SUCCESS;
            }
        }
    }

    logStart("(CLIENT, Linux port)", "Client", CLNTLOG_FILE.c_str());

    if (!strncasecmp(command,"start",5) ) {
	result = start(CLNTPID_FILE.c_str(), WORKDIR.c_str());
    } else
    if (!strncasecmp(command,"run",3) ) {
	result = run();
    } else
    if (!strncasecmp(command,"stop",4)) {
	result = stop(CLNTPID_FILE.c_str());
    } else
    if (!strncasecmp(command,"status",6)) {
	result = status();
    } else
    if (!strncasecmp(command,"help",4)) {
	result = help();
    } else
    if (!strncasecmp(command,"install",7)) {
	cout << "Function not available in Linux/Unix systems." << endl;
	result = 0;
    } else
    if (!strncasecmp(command,"uninstall",9)) {
	cout << "Function not available in Linux/Unix systems." << endl;
	result = 0;
    } else
    {
	help();
    }

    logEnd();

    return result ? EXIT_FAILURE: EXIT_SUCCESS;
}