/rusxmms/librcc

To get this branch, use:
bzr branch http://suren.me/webbzr/rusxmms/librcc

« back to all changes in this revision

Viewing changes to src/rccexternal.c

  • Committer: Suren A. Chilingaryan
  • Date: 2005-07-29 03:26:28 UTC
  • Revision ID: Arch-1:ds@dside.dyndns.org--darksoft-2004%librcc--main--0.1--patch-23
Translation
    - Language Translation using libtranslate is implemented
    - Autoengine sets current charset (option)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <stdlib.h>
 
3
#include <string.h>
 
4
#include <time.h>
 
5
#include <errno.h>
 
6
 
 
7
#include "../config.h"
 
8
 
 
9
#ifdef HAVE_UNISTD_H
 
10
# include <unistd.h>
 
11
#endif /* HAVE_UNISTD_H */
 
12
#ifdef HAVE_FCNTL_H
 
13
# include <fcntl.h>
 
14
#endif /* HAVE_FCNTL_H */
 
15
#ifdef HAVE_SIGNAL_H
 
16
# include <signal.h>
 
17
#endif /* HAVE_SIGNAL_H */
 
18
 
 
19
#ifdef HAVE_SYS_TYPES_H
 
20
# include <sys/types.h>
 
21
#endif /* HAVE_SYS_TYPES_H */
 
22
#ifdef HAVE_SYS_SOCKET_H
 
23
# include <sys/socket.h>
 
24
#endif /* HAVE_SYS_SOCKET_H */
 
25
#ifdef HAVE_SYS_STAT_H
 
26
# include <sys/stat.h>
 
27
#endif /* HAVE_SYS_STAT_H */
 
28
#ifdef HAVE_SYS_UN_H
 
29
# include <sys/un.h>
 
30
#endif /* HAVE_SYS_UN_H */
 
31
#ifdef HAVE_SYS_TIME_H
 
32
# include <sys/time.h>
 
33
#endif /* HAVE_SYS_TIME_H */
 
34
#ifdef HAVE_SYS_SELECT_H
 
35
# include <sys/select.h>
 
36
#endif /* HAVE_SYS_SELECT_H */
 
37
#ifdef HAVE_SYS_WAIT_H
 
38
# include <sys/wait.h>
 
39
#endif /* HAVE_SYS_WAIT_H */
 
40
 
 
41
#include "rccexternal.h"
 
42
#include "internal.h"
 
43
 
 
44
#define RCC_EXT_PROG_NAME "rccexternal"
 
45
 
 
46
static pid_t pid = (pid_t)-1;
 
47
static char *addr = NULL;
 
48
 
 
49
int rccExternalInit() {
 
50
#ifdef HAVE_SIGNAL_H
 
51
    struct sigaction act;
 
52
#endif /* HAVE_SIGNAL_H */
 
53
 
 
54
    if (pid != (pid_t)-1) return 0;
 
55
 
 
56
    if (!addr) {
 
57
        addr = (char*)malloc(strlen(rcc_home_dir)+32);
 
58
        if (!addr) return -1;
 
59
    }
 
60
 
 
61
    pid = fork();
 
62
    if (pid) {
 
63
        if (pid == (pid_t)-1) return -1;
 
64
        sprintf(addr,"%s/.rcc/comm/%lu.sock", rcc_home_dir, (unsigned long)pid);
 
65
 
 
66
#ifdef HAVE_SIGNAL_H
 
67
        act.sa_handler = SIG_IGN;
 
68
        sigemptyset(&act.sa_mask);
 
69
        act.sa_flags = 0;
 
70
        sigaction(SIGPIPE,&act,NULL);
 
71
#endif /* HAVE_SIGNAL_H */
 
72
 
 
73
        return 0;
 
74
    }
 
75
    
 
76
    execl(LIBRCC_DATA_DIR "/" RCC_EXT_PROG_NAME, RCC_EXT_PROG_NAME, NULL);
 
77
    exit(1);
 
78
}
 
79
 
 
80
void rccExternalFree() {
 
81
    if (pid == (pid_t)-1) return;
 
82
    
 
83
    rccExternalConnect(0);    
 
84
    if (addr) free(addr);
 
85
 
 
86
    waitpid(pid, NULL, 0);
 
87
    pid = (pid_t)-1;
 
88
}
 
89
 
 
90
static int rccExternalSetDeadline(struct timeval *tv, unsigned long timeout) {
 
91
    gettimeofday(tv, NULL);
 
92
    tv->tv_sec += (tv->tv_usec + timeout + RCC_EXTERNAL_TIMEOUT) / 1000000;
 
93
    tv->tv_usec = (tv->tv_usec + timeout + RCC_EXTERNAL_TIMEOUT) % 1000000;
 
94
    return 0;
 
95
}
 
96
 
 
97
size_t rccExternalWrite(int s, const char *buffer, ssize_t size, unsigned long timeout) {
 
98
    int err;
 
99
    unsigned char connected = 1;
 
100
    ssize_t writed, res = 0;
 
101
    struct timeval tv;
 
102
    fd_set fdcon;
 
103
 
 
104
    if (s == -1) return -1;
 
105
    
 
106
    for (writed = 0; (writed < size)&&(connected); writed += connected?res:0) {
 
107
        FD_ZERO(&fdcon);
 
108
        FD_SET(s, &fdcon);
 
109
        rccExternalSetDeadline(&tv, timeout);
 
110
        err = select(s+1,NULL,&fdcon,NULL,&tv);
 
111
        if (err<=0) connected = 0;
 
112
        else {
 
113
            res = write(s, buffer + writed, size - writed);
 
114
            if (res<=0) connected = 0;
 
115
        }
 
116
    }
 
117
 
 
118
    return size - writed;
 
119
}
 
120
 
 
121
size_t rccExternalRead(int s, char *buffer, ssize_t size, unsigned long timeout) {
 
122
    int err;
 
123
    unsigned char connected = 1;
 
124
    ssize_t readed, res = 0;
 
125
    struct timeval tv;
 
126
    fd_set fdcon;
 
127
    
 
128
    if (s == -1) return -1;
 
129
    
 
130
    for (readed = 0; (readed < size)&&(connected); readed += connected?res:0) {
 
131
        FD_ZERO(&fdcon);
 
132
        FD_SET(s, &fdcon);
 
133
        rccExternalSetDeadline(&tv, timeout);
 
134
        err = select(s+1,&fdcon,NULL,NULL,&tv);
 
135
        if (err<=0) connected = 0;
 
136
        else {
 
137
            res = read(s, buffer + readed, size - readed);
 
138
            if (res<=0) connected = 0;
 
139
        }
 
140
    }
 
141
 
 
142
    return size - readed;
 
143
}
 
144
 
 
145
int rccExternalConnect(unsigned char module) {
 
146
    int err;
 
147
    int retries = 10;
 
148
    int sock;
 
149
    int flags;
 
150
    struct sockaddr_un mysock;
 
151
    struct timeval tv;
 
152
    struct timespec ts;
 
153
    fd_set fdcon;
 
154
    
 
155
    if (pid == (pid_t)-1) return -1;
 
156
 
 
157
    sock = socket(PF_UNIX, SOCK_STREAM, 0);
 
158
    if (sock<=0) return -1;
 
159
 
 
160
    flags = fcntl(sock,F_GETFL,0);
 
161
    if (flags<0) flags = 0;
 
162
    if (fcntl(sock,F_SETFL,flags|O_NONBLOCK)<0) {
 
163
        close(sock);
 
164
        return -1;
 
165
    }
 
166
        
 
167
    memset(&mysock, 0, sizeof(mysock));
 
168
    mysock.sun_family=AF_UNIX;
 
169
    strncpy(mysock.sun_path,addr,sizeof(mysock.sun_path));
 
170
    mysock.sun_path[sizeof(mysock.sun_path)-1]=0;
 
171
 
 
172
again:
 
173
    if (connect(sock,(struct sockaddr*)&mysock,sizeof(mysock))<0) {
 
174
        if (errno == EINPROGRESS) {
 
175
            FD_ZERO(&fdcon);
 
176
            FD_SET(sock, &fdcon);
 
177
 
 
178
            rccExternalSetDeadline(&tv, 0);
 
179
            err = select(sock+1,&fdcon,NULL,NULL,&tv);
 
180
            if (err<=0) {
 
181
                close(sock);
 
182
                return -1;
 
183
            }
 
184
        } else if ((errno == ENOENT)&&(retries)) {
 
185
            ts.tv_sec = (RCC_EXTERNAL_TIMEOUT/10) / 1000000;
 
186
            ts.tv_nsec = ((RCC_EXTERNAL_TIMEOUT/10) % 1000000)*1000;
 
187
            nanosleep(&ts, NULL);
 
188
            retries--;
 
189
            goto again;
 
190
        } else {
 
191
            close(sock);
 
192
            return -1;
 
193
        }
 
194
    }
 
195
    
 
196
    if (rccExternalWrite(sock, &module, 1, 0)) {
 
197
        close(sock);
 
198
        return -1;
 
199
    }
 
200
 
 
201
    return sock;
 
202
}
 
203
 
 
204
void rccExternalClose(int s) {
 
205
    unsigned char cmd = 0;
 
206
    if (s != -1) {
 
207
        write(s, &cmd, 1);
 
208
        close(s);
 
209
    }
 
210
}