Subversion Repositories HomeAutomation

Rev

Rev 1664 | Rev 1674 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 1664 Rev 1665
1
/*
1
/*
2
 *
2
 *
3
 *  Copyright (C) 2010  Mattias Runge
3
 *  Copyright (C) 2010  Mattias Runge
4
 *
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2 of the License, or
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
8
 *  (at your option) any later version.
9
 *
9
 *
10
 *  This program is distributed in the hope that it will be useful,
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
13
 *  GNU General Public License for more details.
14
 *
14
 *
15
 *  You should have received a copy of the GNU General Public License along
15
 *  You should have received a copy of the GNU General Public License along
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
18
 *
19
 */
19
 */
20
 
20
 
21
#include <string>
21
#include <string>
22
#include <vector>
22
#include <vector>
23
#include <iostream>
23
#include <iostream>
24
 
24
 
25
#include <signal.h>
25
#include <signal.h>
26
#include <stdio.h>
26
#include <stdio.h>
27
#include <stdlib.h>
27
#include <stdlib.h>
28
#include <pwd.h>
28
#include <pwd.h>
29
 
29
 
30
#include <boost/lexical_cast.hpp>
30
#include <boost/lexical_cast.hpp>
31
#include <boost/thread/mutex.hpp>
31
#include <boost/thread/mutex.hpp>
32
#include <boost/thread/condition.hpp>
32
#include <boost/thread/condition.hpp>
33
#include <boost/thread/locks.hpp>
33
#include <boost/thread/locks.hpp>
34
#include <boost/algorithm/string.hpp>
34
#include <boost/algorithm/string.hpp>
35
#include <boost/program_options.hpp>
35
#include <boost/program_options.hpp>
36
 
36
 
37
#include "config.h"
37
#include "config.h"
38
 
38
 
39
#include "net/Manager.h"
39
#include "net/Manager.h"
40
#include "net/Subscriber.h"
40
#include "net/Subscriber.h"
41
#include "net/types.h"
41
#include "net/types.h"
42
 
42
 
43
#include "common/common.h"
43
#include "common/common.h"
44
 
44
 
45
#include <readline/readline.h>
45
#include <readline/readline.h>
46
#include <readline/history.h>
46
#include <readline/history.h>
47
 
47
 
48
using namespace atom;
48
using namespace atom;
49
 
49
 
50
bool finish = false;
50
bool finish = false;
51
common::StringList autocomplete_list;
51
common::StringList autocomplete_list;
52
char* buffer = NULL;
52
char* buffer = NULL;
53
boost::condition on_message_condition;
53
boost::condition on_message_condition;
54
struct termios original_flags;
54
struct termios original_flags;
55
std::string history_filename;
55
std::string history_filename;
56
 
56
 
57
void Handler(int status);
57
void Handler(int status);
58
void CleanUp();
58
void CleanUp();
59
 
59
 
60
char* AutoCompleteGet(const char* text, int state);
60
char* AutoCompleteGet(const char* text, int state);
61
static char** AutoComplete(const char* text, int start, int end);
61
static char** AutoComplete(const char* text, int start, int end);
62
 
62
 
63
std::string GetUserHomeDirectory()
63
std::string GetUserHomeDirectory()
64
{
64
{
65
    return std::string(getpwuid(getuid())->pw_dir);
65
    return std::string(getpwuid(getuid())->pw_dir);
66
}
66
}
67
 
67
 
68
class ConsoleClient : public net::Subscriber
68
class ConsoleClient : public net::Subscriber
69
{
69
{
70
public:
70
public:
71
    typedef boost::shared_ptr<ConsoleClient> Pointer;
71
    typedef boost::shared_ptr<ConsoleClient> Pointer;
72
   
72
   
73
    ConsoleClient(std::string address, unsigned int port)
73
    ConsoleClient(std::string address, unsigned int port)
74
    {
74
    {
75
        this->client_id_ = net::Manager::Instance()->Connect(net::PROTOCOL_TCP, address, port);
75
        this->client_id_ = net::Manager::Instance()->Connect(net::PROTOCOL_TCP, address, port);
76
    }
76
    }
77
   
77
   
78
    virtual ~ConsoleClient()
78
    virtual ~ConsoleClient()
79
    {
79
    {
80
        net::Manager::Instance()->Disconnect(this->client_id_);
80
        net::Manager::Instance()->Disconnect(this->client_id_);
81
 
81
 
82
        this->io_service_.stop();
82
        this->io_service_.stop();
83
    }
83
    }
84
   
84
   
85
    std::string GetPrompt()
85
    std::string GetPrompt()
86
    {
86
    {
87
        return this->prompt_;
87
        return this->prompt_;
88
    }
88
    }
89
   
89
   
90
    void SendResponse(std::string payload)
90
    void SendResponse(std::string payload)
91
    {
91
    {
92
        std::string packet = "RESP";
92
        std::string packet = "RESP";
93
        packet += common::PadNumber(payload.length() + 1, 4);
93
        packet += common::PadNumber(payload.length() + 1, 4);
94
        packet += payload;
94
        packet += payload;
95
       
95
       
96
        net::Manager::Instance()->SendTo(this->client_id_, packet);
96
        net::Manager::Instance()->SendTo(this->client_id_, packet);
97
    }
97
    }
98
   
98
   
99
    void AutoCompleteRequest(unsigned int arg_index, std::string commandline)
99
    void AutoCompleteRequest(unsigned int arg_index, std::string commandline)
100
    {
100
    {
101
        std::string payload = common::PadNumber(arg_index, 4);
101
        std::string payload = common::PadNumber(arg_index, 4);
102
        payload += commandline;
102
        payload += commandline;
103
       
103
       
104
        std::string packet = "COMP";
104
        std::string packet = "COMP";
105
        packet += common::PadNumber(payload.length() + 1, 4);
105
        packet += common::PadNumber(payload.length() + 1, 4);
106
        packet += payload;
106
        packet += payload;
107
       
107
       
108
        net::Manager::Instance()->SendTo(this->client_id_, packet);
108
        net::Manager::Instance()->SendTo(this->client_id_, packet);
109
    }
109
    }
110
   
110
   
111
private:
111
private:
112
    net::ClientId client_id_;
112
    net::ClientId client_id_;
113
    std::string prompt_;
113
    std::string prompt_;
114
   
-
 
115
   
114
   
116
    void SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
115
    void SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
117
    {
116
    {
118
        if (client_state != net::CLIENT_STATE_CONNECTED)
117
        if (client_state != net::CLIENT_STATE_CONNECTED)
119
        {
118
        {
120
            std::cout << "Disconnected from server." << std::endl;
119
            std::cout << "Disconnected from server." << std::endl;
121
           
120
           
122
            this->client_id_ = 0;
121
            this->client_id_ = 0;
123
            finish = true;
122
            finish = true;
124
            on_message_condition.notify_all();
123
            on_message_condition.notify_all();
125
        }
124
        }
126
    }
125
    }
127
   
126
   
128
    void SlotOnNewDataHandler(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
127
    void SlotOnNewDataHandler(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
129
    {
128
    {
130
        std::string s(data.ToCharString());
129
        std::string s(data.ToCharString());
131
 
130
 
132
        while (s.length() > 0)
131
        while (s.length() > 0)
133
        {
132
        {
134
            std::string command = s.substr(0, 4);
133
            std::string command = s.substr(0, 4);
135
            unsigned int payload_length = boost::lexical_cast<unsigned int>(s.substr(4, 4));
134
            unsigned int payload_length = boost::lexical_cast<unsigned int>(s.substr(4, 4));
136
           
135
           
137
            if (command == "TEXT")
136
            if (command == "TEXT")
138
            {
137
            {
139
                std::cout << s.substr(8, payload_length - 1) << std::flush;
138
                std::cout << s.substr(8, payload_length - 1) << std::flush;
140
            }
139
            }
141
            else if (command == "PROM")
140
            else if (command == "PROM")
142
            {
141
            {
143
                this->prompt_ = s.substr(8, payload_length - 1);
142
                this->prompt_ = s.substr(8, payload_length - 1);
144
                on_message_condition.notify_all();
143
                on_message_condition.notify_all();
145
            }
144
            }
146
            else if (command == "COMP")
145
            else if (command == "COMP")
147
            {
146
            {
148
                autocomplete_list.clear();
147
                autocomplete_list.clear();
149
               
148
               
150
                if (payload_length > 0)
149
                if (payload_length > 0)
151
                {
150
                {
152
                    std::string payload = s.substr(8, payload_length - 1);
151
                    std::string payload = s.substr(8, payload_length - 1);
153
                   
152
                   
154
                    if (payload.length() > 0)
153
                    if (payload.length() > 0)
155
                    {
154
                    {
156
                        boost::algorithm::split(autocomplete_list, payload, boost::is_any_of("\n"), boost::algorithm::token_compress_on);
155
                        boost::algorithm::split(autocomplete_list, payload, boost::is_any_of("\n"), boost::algorithm::token_compress_on);
157
                    }
156
                    }
158
                }
157
                }
159
               
158
               
160
                on_message_condition.notify_all();
159
                on_message_condition.notify_all();
161
            }
160
            }
162
            else
161
            else
163
            {
162
            {
164
                std::cerr << "Unknown data received: " << s << std::endl;
163
                std::cerr << "Unknown data received: " << s << std::endl;
165
                finish = true;
164
                finish = true;
166
                on_message_condition.notify_all();
165
                on_message_condition.notify_all();
167
                break;
166
                break;
168
            }
167
            }
169
           
168
           
170
            if (8 + payload_length >= s.length())
169
            if (8 + payload_length >= s.length())
171
            {
170
            {
172
                break;
171
                break;
173
            }
172
            }
174
           
173
           
175
            s = s.substr(8 + payload_length);
174
            s = s.substr(8 + payload_length);
176
        }
175
        }
177
    }
176
    }
178
};
177
};
179
 
178
 
180
ConsoleClient::Pointer cc;
179
ConsoleClient::Pointer cc;
181
 
180
 
182
 
181
 
183
int main(int argc, char **argv)
182
int main(int argc, char **argv)
184
{
183
{
185
    // Signal handlers
184
    // Signal handlers
186
    signal(SIGTERM, Handler);
185
    signal(SIGTERM, Handler);
187
    signal(SIGINT, Handler);
186
    signal(SIGINT, Handler);
188
    signal(SIGQUIT, Handler);
187
    signal(SIGQUIT, Handler);
189
    signal(SIGABRT, Handler);
188
    signal(SIGABRT, Handler);
190
    signal(SIGPIPE, Handler);
189
    signal(SIGPIPE, Handler);
191
   
190
   
192
    boost::mutex guard_mutex;
191
    boost::mutex guard_mutex;
193
   
192
   
194
    // Setup readline
193
    // Setup readline
195
    history_filename = GetUserHomeDirectory() + "/.atomic_history";
194
    history_filename = GetUserHomeDirectory() + "/.atomic_history";
196
    read_history(history_filename.data());
195
    read_history(history_filename.data());
197
   
196
   
198
    rl_attempted_completion_function = AutoComplete;
197
    rl_attempted_completion_function = AutoComplete;
199
   
198
   
200
    // Save command line state
199
    // Save command line state
201
    tcgetattr(fileno(stdin), &original_flags);
200
    tcgetattr(fileno(stdin), &original_flags);
202
   
201
   
203
    // Parse commandline
202
    // Parse commandline
204
    boost::program_options::options_description command_line;
203
    boost::program_options::options_description command_line;
205
    boost::program_options::variables_map variable_map;
204
    boost::program_options::variables_map variable_map;
206
   
205
   
207
    command_line.add_options()
206
    command_line.add_options()
208
    ("help,h",    "produce help message")
207
    ("help,h",    "produce help message")
209
    ("command,c", boost::program_options::value<std::string>()->default_value(""), "command")
208
    ("command,c", boost::program_options::value<std::string>()->default_value(""), "command")
210
    ("server,s",  boost::program_options::value<std::string>()->default_value("localhost"), "server address")
209
    ("server,s",  boost::program_options::value<std::string>()->default_value("localhost"), "server address")
211
    ("port,p",    boost::program_options::value<unsigned int>()->default_value(1202), "server port");
210
    ("port,p",    boost::program_options::value<unsigned int>()->default_value(1202), "server port");
212
   
211
   
213
    try
212
    try
214
    {
213
    {
215
        boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(command_line).run(), variable_map);
214
        boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(command_line).run(), variable_map);
216
    }
215
    }
217
    catch (boost::program_options::unknown_option e)
216
    catch (boost::program_options::unknown_option e)
218
    {
217
    {
219
        std::cerr << e.what() << std::endl;
218
        std::cerr << e.what() << std::endl;
220
        std::cout << command_line << std::endl;
219
        std::cout << command_line << std::endl;
221
        CleanUp();
220
        CleanUp();
222
        return EXIT_FAILURE;
221
        return EXIT_FAILURE;
223
    }
222
    }
224
    catch (boost::program_options::invalid_syntax e)
223
    catch (boost::program_options::invalid_syntax e)
225
    {
224
    {
226
        std::cerr << e.what() << std::endl;
225
        std::cerr << e.what() << std::endl;
227
        std::cout << command_line << std::endl;
226
        std::cout << command_line << std::endl;
228
        CleanUp();
227
        CleanUp();
229
        return EXIT_FAILURE;
228
        return EXIT_FAILURE;
230
    }
229
    }
231
   
230
   
232
    if (variable_map.count("help") != 0)
231
    if (variable_map.count("help") != 0)
233
    {
232
    {
234
        std::cout << command_line << std::endl;
233
        std::cout << command_line << std::endl;
235
        CleanUp();
234
        CleanUp();
236
        return EXIT_SUCCESS;
235
        return EXIT_SUCCESS;
237
    }
236
    }
238
   
237
   
239
    net::Manager::Create();
238
    net::Manager::Create();
240
 
239
 
241
    if (variable_map["command"].as<std::string>() == "")
240
    if (variable_map["command"].as<std::string>() == "")
242
    {
241
    {
243
        std::cout << "\033[29;1mAtom Interactive Console, version " + std::string(VERSION) + " starting...\033[0m" << std::endl;
242
        std::cout << "\033[29;1mAtom Interactive Console, version " + std::string(VERSION) + " starting...\033[0m" << std::endl;
244
        std::cout << "\033[29;1mReleased under GPL version 2.\033[0m" << std::endl;
243
        std::cout << "\033[29;1mReleased under GPL version 2.\033[0m" << std::endl;
245
        std::cout << "Written by Mattias Runge 2010." << std::endl;
244
        std::cout << "Written by Mattias Runge 2010." << std::endl;
246
       
245
       
247
        std::cout << "Connecting to " << variable_map["server"].as<std::string>().data() << ":" << variable_map["port"].as<unsigned int>() << "..." << std::endl;
246
        std::cout << "Connecting to " << variable_map["server"].as<std::string>().data() << ":" << variable_map["port"].as<unsigned int>() << "..." << std::endl;
248
    }
247
    }
249
   
248
   
250
    try
249
    try
251
    {
250
    {
252
        cc = ConsoleClient::Pointer(new ConsoleClient(variable_map["server"].as<std::string>(), variable_map["port"].as<unsigned int>()));
251
        cc = ConsoleClient::Pointer(new ConsoleClient(variable_map["server"].as<std::string>(), variable_map["port"].as<unsigned int>()));
253
    }
252
    }
254
    catch (std::runtime_error& e)
253
    catch (std::runtime_error& e)
255
    {
254
    {
256
        std::cerr << "Connection error: " << e.what() << std::endl;
255
        std::cerr << "Connection error: " << e.what() << std::endl;
257
        CleanUp();
256
        CleanUp();
258
        return EXIT_FAILURE;
257
        return EXIT_FAILURE;
259
    }
258
    }
260
   
259
   
261
    if (variable_map["command"].as<std::string>() != "")
260
    if (variable_map["command"].as<std::string>() != "")
262
    {
261
    {
263
        boost::mutex::scoped_lock guard(guard_mutex);
262
        boost::mutex::scoped_lock guard(guard_mutex);
264
        on_message_condition.wait(guard);
263
        on_message_condition.wait(guard);
265
       
264
       
266
        if (!finish)
265
        if (!finish)
267
        {
266
        {
268
            cc->SendResponse(variable_map["command"].as<std::string>());
267
            cc->SendResponse(variable_map["command"].as<std::string>());
269
           
268
           
270
            if (!finish)
269
            if (!finish)
271
            {
270
            {
272
                on_message_condition.wait(guard);
271
                on_message_condition.wait(guard);
273
            }
272
            }
274
        }
273
        }
275
    }
274
    }
276
    else
275
    else
277
    {
276
    {
278
        while (true)
277
        while (true)
279
        {
278
        {
280
            boost::mutex::scoped_lock guard(guard_mutex);
279
            boost::mutex::scoped_lock guard(guard_mutex);
281
            on_message_condition.wait(guard);
280
            on_message_condition.wait(guard);
282
           
281
           
283
            if (finish)
282
            if (finish)
284
            {
283
            {
285
                break;
284
                break;
286
            }
285
            }
287
           
286
           
288
            while ((buffer = readline(cc->GetPrompt().data())) != NULL)
287
            while ((buffer = readline(cc->GetPrompt().data())) != NULL)
289
            {
288
            {
-
 
289
                if (finish)
-
 
290
                {
-
 
291
                    break;
-
 
292
                }
-
 
293
               
290
                if (strlen(buffer) == 0)
294
                if (strlen(buffer) == 0)
291
                {
295
                {
292
                    continue;
296
                    continue;
293
                }
297
                }
294
               
298
               
-
 
299
                break;
-
 
300
            }
-
 
301
           
-
 
302
            if (finish)
-
 
303
            {
295
                break;
304
                break;
296
            }
305
            }
297
           
306
           
298
            cc->SendResponse(buffer);
307
            cc->SendResponse(buffer);
299
            add_history(buffer);
308
            add_history(buffer);
300
        }
309
        }
301
    }
310
    }
302
   
311
   
303
    CleanUp();
312
    CleanUp();
304
   
313
   
305
    return EXIT_SUCCESS;
314
    return EXIT_SUCCESS;
306
}
315
}
307
 
316
 
308
static char** AutoComplete(const char* text, int start, int end)
317
static char** AutoComplete(const char* text, int start, int end)
309
{
318
{
310
    unsigned int count = 0;
319
    unsigned int count = 0;
311
    boost::mutex guard_mutex;
320
    boost::mutex guard_mutex;
312
 
321
 
313
    for (unsigned int n = 0; n < start; n++)
322
    for (unsigned int n = 0; n < start; n++)
314
    {
323
    {
315
        if (rl_line_buffer[n] == ' ')
324
        if (rl_line_buffer[n] == ' ')
316
        {
325
        {
317
            count++;
326
            count++;
318
        }
327
        }
319
    }
328
    }
320
   
329
   
321
    cc->AutoCompleteRequest(count, rl_line_buffer);
330
    cc->AutoCompleteRequest(count, rl_line_buffer);
322
   
331
   
323
    boost::mutex::scoped_lock guard(guard_mutex);
332
    boost::mutex::scoped_lock guard(guard_mutex);
324
    on_message_condition.wait(guard);
333
    on_message_condition.wait(guard);
325
   
334
   
326
    /*if (autocomplete_list.size() == 0)
335
    /*if (autocomplete_list.size() == 0)
327
    {
336
    {
328
        return NULL;
337
        return NULL;
329
    }*/
338
    }*/
330
   
339
   
331
    return rl_completion_matches(text, &AutoCompleteGet);
340
    return rl_completion_matches(text, &AutoCompleteGet);
332
}
341
}
333
 
342
 
334
char* AutoCompleteGet(const char* text, int state)
343
char* AutoCompleteGet(const char* text, int state)
335
{
344
{
336
    static int index = 0;
345
    static int index = 0;
337
    int length = strlen(text);
346
    int length = strlen(text);
338
    std::string name;
347
    std::string name;
339
   
348
   
340
    if (!state) // First run
349
    if (!state) // First run
341
    {
350
    {
342
        index = 0;
351
        index = 0;
343
    }
352
    }
344
   
353
   
345
    while (autocomplete_list.size() > index)
354
    while (autocomplete_list.size() > index)
346
    {
355
    {
347
        name = autocomplete_list[index];
356
        name = autocomplete_list[index];
348
       
357
       
349
        index++;
358
        index++;
350
       
359
       
351
        if (strncmp(name.data(), text, length) == 0)
360
        if (strncmp(name.data(), text, length) == 0)
352
        {
361
        {
353
            char *result = (char*)malloc(name.size() + 1);
362
            char *result = (char*)malloc(name.size() + 1);
354
            strcpy(result, name.data());
363
            strcpy(result, name.data());
355
           
364
           
356
            return result;
365
            return result;
357
        }
366
        }
358
    }
367
    }
359
   
368
   
360
    return NULL;
369
    return NULL;
361
}
370
}
362
 
371
 
363
void CleanUp()
372
void CleanUp()
364
{
373
{
365
    std::cout << std::endl;
374
    std::cout << std::endl;
366
    //std::cout << "Cleaning up..." << std::endl;
375
    //std::cout << "Cleaning up..." << std::endl;
367
 
376
 
368
    write_history(history_filename.data());
377
    write_history(history_filename.data());
369
   
378
   
370
    cc.reset();
379
    cc.reset();
371
   
380
   
372
    net::Manager::Delete();
381
    net::Manager::Delete();
373
   
382
   
374
    if (buffer != NULL)
383
    if (buffer != NULL)
375
    {
384
    {
376
        free(buffer);
385
        free(buffer);
377
    }
386
    }
378
   
387
   
379
    //std::cout << "Thank you for using Atom. Goodbye!" << std::endl;
388
    //std::cout << "Thank you for using Atom. Goodbye!" << std::endl;
380
   
389
   
381
    tcsetattr(fileno(stdin), TCSANOW, &original_flags); // Restore
390
    tcsetattr(fileno(stdin), TCSANOW, &original_flags); // Restore
382
}
391
}
383
 
392
 
384
void Handler(int status)
393
void Handler(int status)
385
{
394
{
386
    std::string signal_name = "Unknown";
395
    std::string signal_name = "Unknown";
387
   
396
   
388
    switch (status)
397
    switch (status)
389
    {
398
    {
390
        case SIGTERM:
399
        case SIGTERM:
391
        {
400
        {
392
            signal_name = "Terminate";
401
            signal_name = "Terminate";
393
            break;
402
            break;
394
        }  
403
        }  
395
        case SIGINT:
404
        case SIGINT:
396
        {
405
        {
397
            signal_name = "Interupt";
406
            signal_name = "Interupt";
398
            break;
407
            break;
399
        }  
408
        }  
400
        case SIGQUIT:
409
        case SIGQUIT:
401
        {
410
        {
402
            signal_name = "Quit";
411
            signal_name = "Quit";
403
            break;
412
            break;
404
        }  
413
        }  
405
        case SIGABRT:
414
        case SIGABRT:
406
        {
415
        {
407
            signal_name = "Abort";
416
            signal_name = "Abort";
408
            break;
417
            break;
409
        }  
418
        }  
410
        case SIGIO:
419
        case SIGIO:
411
        {
420
        {
412
            signal_name = "I/O";
421
            signal_name = "I/O";
413
            break;
422
            break;
414
        }  
423
        }  
415
        case SIGPIPE:
424
        case SIGPIPE:
416
        {
425
        {
417
            signal_name = "Pipe";
426
            signal_name = "Pipe";
418
            break;
427
            break;
419
        }
428
        }
420
    }
429
    }
421
   
430
   
422
   
431
   
423
    if (status != SIGPIPE)
432
    if (status != SIGPIPE)
424
    {
433
    {
425
        CleanUp();
434
        CleanUp();
426
        exit(0);
435
        exit(0);
427
    }
436
    }
428
}
437
}