Gammu internals  1.38.0
proxy.c File Reference
#include "../../gsmstate.h"
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "../../gsmcomon.h"
#include "../devfunc.h"
#include "proxy.h"
#include "../../../helper/string.h"
Include dependency graph for proxy.c:

Go to the source code of this file.

Macros

#define _GNU_SOURCE   /* For asprintf */
 
#define _PATH_BSHELL   "/bin/sh"
 

Functions

static char * expand_proxy_command (const char *proxy_command)
 
static GSM_Error proxy_connect (GSM_StateMachine *s, GSM_Device_ProxyData *proxydata, const char *proxy_command)
 
void kill_proxy_command (pid_t proxy_command_pid)
 
GSM_Error proxy_open (GSM_StateMachine *s)
 
int proxy_read (GSM_StateMachine *s, void *buf, size_t nbytes)
 
static ssize_t write_nosigpipe (int fd, const void *buf, size_t len)
 
int proxy_write (GSM_StateMachine *s, const void *buf, size_t nbytes)
 
GSM_Error proxy_close (GSM_StateMachine *s)
 

Variables

GSM_Device_Functions ProxyDevice
 

Macro Definition Documentation

§ _GNU_SOURCE

#define _GNU_SOURCE   /* For asprintf */

Definition at line 1 of file proxy.c.

§ _PATH_BSHELL

#define _PATH_BSHELL   "/bin/sh"

Definition at line 32 of file proxy.c.

Referenced by proxy_connect().

Function Documentation

§ expand_proxy_command()

static char* expand_proxy_command ( const char *  proxy_command)
static

Definition at line 20 of file proxy.c.

Referenced by proxy_connect().

21 {
22  char *ret;
23 
24  ret = NULL;
25  if (asprintf(&ret, "exec %s", proxy_command) < 0) {
26  return NULL;
27  }
28  return ret;
29 }

§ kill_proxy_command()

void kill_proxy_command ( pid_t  proxy_command_pid)

Definition at line 119 of file proxy.c.

Referenced by proxy_close().

120 {
121  /*
122  * Send SIGHUP to proxy command if used. We don't wait() in
123  * case it hangs and instead rely on init to reap the child
124  */
125  if (proxy_command_pid > 1)
126  kill(proxy_command_pid, SIGHUP);
127 }

§ proxy_close()

GSM_Error proxy_close ( GSM_StateMachine s)

Definition at line 203 of file proxy.c.

References GSM_Device::Data, _GSM_StateMachine::Device, ERR_NONE, GSM_Device_ProxyData::hProcess, GSM_Device_ProxyData::hRead, GSM_Device_ProxyData::hWrite, kill_proxy_command(), and GSM_Device::Proxy.

204 {
206  close(s->Device.Data.Proxy.hRead);
207  close(s->Device.Data.Proxy.hWrite);
208  return ERR_NONE;
209 }
void kill_proxy_command(pid_t proxy_command_pid)
Definition: proxy.c:119
GSM_Device_ProxyData Proxy
Definition: gsmstate.h:329
union GSM_Device::@0 Data
pid_t hProcess
Definition: proxy.h:9
GSM_Device Device
Definition: gsmstate.h:1429

§ proxy_connect()

static GSM_Error proxy_connect ( GSM_StateMachine s,
GSM_Device_ProxyData proxydata,
const char *  proxy_command 
)
static

Definition at line 39 of file proxy.c.

References _PATH_BSHELL, dbgprintf, ERR_DEVICEOPENERROR, ERR_MOREMEMORY, ERR_NONE, expand_proxy_command(), GSM_OSErrorInfo(), GSM_Device_ProxyData::hProcess, GSM_Device_ProxyData::hRead, and GSM_Device_ProxyData::hWrite.

Referenced by proxy_open().

40 {
41  char *command_string;
42  int pin[2], pout[2];
43  pid_t pid;
44  const char *shell;
45 
46  if ((shell = getenv("SHELL")) == NULL || *shell == '\0') {
47  shell = _PATH_BSHELL;
48  }
49 
50  /* Create pipes for communicating with the proxy. */
51  if (pipe(pin) < 0 || pipe(pout) < 0) {
52  GSM_OSErrorInfo(s, "Could not create pipes to communicate with the proxy");
53  return ERR_DEVICEOPENERROR;
54  }
55 
56  command_string = expand_proxy_command(proxy_command);
57  if (command_string == NULL) {
58  return ERR_MOREMEMORY;
59  }
60  dbgprintf(NULL, "Executing proxy command: %.500s", command_string);
61 
62  /* Fork and execute the proxy command. */
63  if ((pid = fork()) == 0) {
64  const char * argv[10];
65 
66  /* Child. Permanently give up superuser privileges. */
67  //permanently_drop_suid(original_real_uid);
68 
69  /* Redirect stdin and stdout. */
70  close(pin[1]);
71  if (pin[0] != 0) {
72  if (dup2(pin[0], 0) < 0)
73  perror("dup2 stdin");
74  close(pin[0]);
75  }
76  close(pout[0]);
77  if (dup2(pout[1], 1) < 0)
78  perror("dup2 stdout");
79  /* Cannot be 1 because pin allocated two descriptors. */
80  close(pout[1]);
81 
82  /* Stderr is left as it is so that error messages get
83  printed on the user's terminal. */
84  argv[0] = shell;
85  argv[1] = "-c";
86  argv[2] = command_string;
87  argv[3] = NULL;
88 
89  /* Execute the proxy command. Note that we gave up any
90  extra privileges above. */
91  signal(SIGPIPE, SIG_DFL);
92  execv(argv[0], (char **)argv);
93  perror(argv[0]);
94  exit(1);
95  }
96  /* Parent. */
97  if (pid < 0) {
98  GSM_OSErrorInfo(s, "fork failed");
99  return ERR_DEVICEOPENERROR;
100  } else
101  proxydata->hProcess = pid; /* save pid to clean up later */
102 
103  /* Close child side of the descriptors. */
104  close(pin[0]);
105  close(pout[1]);
106 
107  /* Free the command name. */
108  free(command_string);
109 
110  /* Set the connection file descriptors. */
111  proxydata->hRead = pout[0];
112  proxydata->hWrite = pin[1];
113 
114  /* Indicate OK return */
115  return ERR_NONE;
116 }
static char * expand_proxy_command(const char *proxy_command)
Definition: proxy.c:20
pid_t hProcess
Definition: proxy.h:9
#define _PATH_BSHELL
Definition: proxy.c:32
void GSM_OSErrorInfo(GSM_StateMachine *s, const char *description)
Definition: gsmstate.c:1593
#define dbgprintf
Definition: debug.h:72

§ proxy_open()

GSM_Error proxy_open ( GSM_StateMachine s)

Definition at line 130 of file proxy.c.

References _GSM_StateMachine::CurrentConfig, GSM_Device::Data, GSM_Config::Device, _GSM_StateMachine::Device, GSM_Device::Proxy, and proxy_connect().

131 {
132  return proxy_connect(s, &s->Device.Data.Proxy, s->CurrentConfig->Device);
133 }
GSM_Config * CurrentConfig
Definition: gsmstate.h:1415
GSM_Device_ProxyData Proxy
Definition: gsmstate.h:329
union GSM_Device::@0 Data
static GSM_Error proxy_connect(GSM_StateMachine *s, GSM_Device_ProxyData *proxydata, const char *proxy_command)
Definition: proxy.c:39
GSM_Device Device
Definition: gsmstate.h:1429

§ proxy_read()

int proxy_read ( GSM_StateMachine s,
void *  buf,
size_t  nbytes 
)

Definition at line 135 of file proxy.c.

References GSM_Device::Data, _GSM_StateMachine::Device, GSM_OSErrorInfo(), GSM_Device_ProxyData::hRead, and GSM_Device::Proxy.

136 {
138  struct timeval timeout2;
139  fd_set readfds;
140  int actual = 0;
141 
142  FD_ZERO(&readfds);
143  FD_SET(d->hRead, &readfds);
144 
145  timeout2.tv_sec = 0;
146  timeout2.tv_usec = 50000;
147 
148  if (select(d->hRead+1, &readfds, NULL, NULL, &timeout2)) {
149  actual = read(d->hRead, buf, nbytes);
150  if (actual == -1) GSM_OSErrorInfo(s,"proxy_read");
151  }
152  return actual;
153 }
GSM_Device_ProxyData Proxy
Definition: gsmstate.h:329
union GSM_Device::@0 Data
void GSM_OSErrorInfo(GSM_StateMachine *s, const char *description)
Definition: gsmstate.c:1593
GSM_Device Device
Definition: gsmstate.h:1429

§ proxy_write()

int proxy_write ( GSM_StateMachine s,
const void *  buf,
size_t  nbytes 
)

Definition at line 175 of file proxy.c.

References _GSM_StateMachine::ConnectionType, GSM_Device::Data, _GSM_StateMachine::Device, GCT_FBUS2PL2303, GSM_OSErrorInfo(), GSM_Device_ProxyData::hWrite, GSM_Device::Proxy, smprintf(), and write_nosigpipe().

176 {
178  int ret;
179  size_t actual = 0;
180  const unsigned char *buffer = (const unsigned char *)buf; /* Just to have correct type */
181 
182  do {
183  ret = write_nosigpipe(d->hWrite, buffer, nbytes - actual);
184  if (ret < 0) {
185  if (errno == EAGAIN) {
186  usleep(1000);
187  continue;
188  }
189  if (actual != nbytes) {
190  GSM_OSErrorInfo(s, "proxy_write");
191  smprintf(s, "Wanted to write %ld bytes, but %ld were written\n",
192  (long)nbytes, (long)actual);
193  }
194  return actual;
195  }
196  actual += ret;
197  buffer += ret;
198  if (s->ConnectionType == GCT_FBUS2PL2303) usleep(1000);
199  } while (actual < nbytes);
200  return actual;
201 }
GSM_Device_ProxyData Proxy
Definition: gsmstate.h:329
union GSM_Device::@0 Data
GSM_ConnectionType ConnectionType
Definition: gsmstate.h:1402
static ssize_t write_nosigpipe(int fd, const void *buf, size_t len)
Definition: proxy.c:156
void GSM_OSErrorInfo(GSM_StateMachine *s, const char *description)
Definition: gsmstate.c:1593
GSM_Device Device
Definition: gsmstate.h:1429
int smprintf(GSM_StateMachine *s, const char *format,...)
Definition: debug.c:261

§ write_nosigpipe()

static ssize_t write_nosigpipe ( int  fd,
const void *  buf,
size_t  len 
)
static

Definition at line 156 of file proxy.c.

Referenced by proxy_write().

157 {
158  sigset_t oldset, newset;
159  ssize_t result;
160  siginfo_t si;
161  struct timespec ts = {0};
162 
163  sigemptyset(&newset);
164  sigaddset(&newset, SIGPIPE);
165  pthread_sigmask(SIG_BLOCK, &newset, &oldset);
166 
167  result = write(fd, buf, len);
168 
169  while (sigtimedwait(&newset, &si, &ts)>=0 || errno != EAGAIN);
170  pthread_sigmask(SIG_SETMASK, &oldset, 0);
171 
172  return result;
173 }