00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include <stdio.h>
00015
#include <unistd.h>
00016
#include <stdlib.h>
00017
#include <termios.h>
00018
#include <string.h>
00019
#include <sys/ioctl.h>
00020
#include <asterisk/io.h>
00021
#include <asterisk/logger.h>
00022
00023
#ifdef DEBUG_IO
00024
#define DEBUG DEBUG_M
00025
#else
00026 #define DEBUG(a)
00027
#endif
00028
00029
00030
00031
00032 struct io_rec {
00033 ast_io_cb callback;
00034 void *
data;
00035 int *
id;
00036 };
00037
00038
00039
00040
00041
00042
00043
00044
00045 #define GROW_SHRINK_SIZE 512
00046
00047
00048
00049 struct io_context {
00050
00051 struct pollfd *
fds;
00052
00053 struct io_rec *
ior;
00054
00055 unsigned int fdcnt;
00056
00057 unsigned int maxfdcnt;
00058
00059 int current_ioc;
00060
00061 int needshrink;
00062 };
00063
00064
00065 struct io_context *
io_context_create(
void)
00066 {
00067
00068
struct io_context *tmp;
00069 tmp =
malloc(
sizeof(
struct io_context));
00070
if (tmp) {
00071 tmp->needshrink = 0;
00072 tmp->fdcnt = 0;
00073 tmp->maxfdcnt =
GROW_SHRINK_SIZE/2;
00074 tmp->current_ioc = -1;
00075 tmp->fds =
malloc((
GROW_SHRINK_SIZE/2) *
sizeof(
struct pollfd));
00076
if (!tmp->fds) {
00077
free(tmp);
00078 tmp = NULL;
00079 }
else {
00080 memset(tmp->fds, 0, (
GROW_SHRINK_SIZE/2) *
sizeof(
struct pollfd));
00081 tmp->ior =
malloc((
GROW_SHRINK_SIZE/2) *
sizeof(
struct io_rec));
00082
if (!tmp->ior) {
00083
free(tmp->fds);
00084
free(tmp);
00085 tmp = NULL;
00086 }
else
00087 memset(tmp->ior, 0, (
GROW_SHRINK_SIZE/2) *
sizeof(
struct io_rec));
00088 }
00089 }
00090
return tmp;
00091 }
00092
00093 void io_context_destroy(
struct io_context *ioc)
00094 {
00095
00096
if (ioc->
fds)
00097
free(ioc->
fds);
00098
if (ioc->
ior)
00099
free(ioc->
ior);
00100
free(ioc);
00101 }
00102
00103
static int io_grow(
struct io_context *ioc)
00104 {
00105
00106
00107
00108
00109
void *tmp;
00110
DEBUG(
ast_log(LOG_DEBUG,
"io_grow()\n"));
00111 ioc->
maxfdcnt +=
GROW_SHRINK_SIZE;
00112 tmp =
realloc(ioc->
ior, (ioc->
maxfdcnt + 1) *
sizeof(
struct io_rec));
00113
if (tmp) {
00114 ioc->
ior = (
struct io_rec *)tmp;
00115 tmp =
realloc(ioc->
fds, (ioc->
maxfdcnt + 1) *
sizeof(
struct pollfd));
00116
if (tmp) {
00117 ioc->
fds = tmp;
00118 }
else {
00119
00120
00121
00122
00123
00124
00125 ioc->
maxfdcnt -=
GROW_SHRINK_SIZE;
00126
return -1;
00127 }
00128
00129 }
else {
00130
00131
00132
00133 ioc->
maxfdcnt -=
GROW_SHRINK_SIZE;
00134
return -1;
00135 }
00136
return 0;
00137 }
00138
00139 int *
ast_io_add(
struct io_context *ioc,
int fd,
ast_io_cb callback,
short events,
void *data)
00140 {
00141
00142
00143
00144
00145
00146
int *ret;
00147
DEBUG(
ast_log(
LOG_DEBUG,
"ast_io_add()\n"));
00148
if (ioc->
fdcnt >= ioc->
maxfdcnt) {
00149
00150
00151
00152
00153
if (io_grow(ioc))
00154
return NULL;
00155 }
00156
00157
00158
00159
00160
00161
00162 ioc->
fds[ioc->
fdcnt].
fd = fd;
00163 ioc->
fds[ioc->
fdcnt].
events = events;
00164 ioc->
ior[ioc->
fdcnt].
callback = callback;
00165 ioc->
ior[ioc->
fdcnt].
data = data;
00166 ioc->
ior[ioc->
fdcnt].
id = (
int *)
malloc(
sizeof(
int));
00167
00168
if (!ioc->
ior[ioc->
fdcnt].
id)
00169
return NULL;
00170 *(ioc->
ior[ioc->
fdcnt].
id) = ioc->
fdcnt;
00171 ret = ioc->
ior[ioc->
fdcnt].
id;
00172 ioc->
fdcnt++;
00173
return ret;
00174 }
00175
00176 int *
ast_io_change(
struct io_context *ioc,
int *
id,
int fd, ast_io_cb callback,
short events,
void *data)
00177 {
00178
if (*
id < ioc->
fdcnt) {
00179
if (fd > -1)
00180 ioc->
fds[*
id].
fd = fd;
00181
if (callback)
00182 ioc->
ior[*
id].
callback = callback;
00183
if (events)
00184 ioc->
fds[*
id].
events = events;
00185
if (data)
00186 ioc->
ior[*
id].
data = data;
00187
return id;
00188 }
else return NULL;
00189 }
00190
00191
static int io_shrink(
struct io_context *ioc)
00192 {
00193
int getfrom;
00194
int putto = 0;
00195
00196
00197
00198
00199
00200
for (getfrom=0;getfrom<ioc->
fdcnt;getfrom++) {
00201
if (ioc->
ior[getfrom].
id) {
00202
00203
if (getfrom != putto) {
00204 ioc->
fds[putto] = ioc->
fds[getfrom];
00205 ioc->
ior[putto] = ioc->
ior[getfrom];
00206 *(ioc->
ior[putto].
id) = putto;
00207 }
00208 putto++;
00209 }
00210 }
00211 ioc->
fdcnt = putto;
00212 ioc->
needshrink = 0;
00213
00214
00215
return 0;
00216 }
00217
00218 int ast_io_remove(
struct io_context *ioc,
int *_id)
00219 {
00220
int x;
00221
if (!_id) {
00222
ast_log(
LOG_WARNING,
"Asked to remove NULL?\n");
00223
return -1;
00224 }
00225
for (x=0;x<ioc->
fdcnt;x++) {
00226
if (ioc->
ior[x].
id == _id) {
00227
00228
free(ioc->
ior[x].
id);
00229 ioc->
ior[x].
id = NULL;
00230 ioc->
fds[x].
events = 0;
00231 ioc->
fds[x].
revents = 0;
00232 ioc->
needshrink = 1;
00233
if (!ioc->
current_ioc)
00234 io_shrink(ioc);
00235
return 0;
00236 }
00237 }
00238
00239
ast_log(
LOG_NOTICE,
"Unable to remove unknown id %p\n", _id);
00240
return -1;
00241 }
00242
00243 int ast_io_wait(
struct io_context *ioc,
int howlong)
00244 {
00245
00246
00247
00248
00249
00250
int res;
00251
int x;
00252
int origcnt;
00253
DEBUG(
ast_log(
LOG_DEBUG,
"ast_io_wait()\n"));
00254 res =
poll(ioc->
fds, ioc->
fdcnt, howlong);
00255
if (res > 0) {
00256
00257
00258
00259 origcnt = ioc->
fdcnt;
00260
for(x=0;x<origcnt;x++) {
00261
00262
00263
if (ioc->
fds[x].
revents && ioc->
ior[x].
id) {
00264
00265 ioc->
current_ioc = *ioc->
ior[x].
id;
00266
if (ioc->
ior[x].
callback) {
00267
if (!ioc->
ior[x].
callback(ioc->
ior[x].
id, ioc->
fds[x].
fd, ioc->
fds[x].
revents, ioc->
ior[x].
data)) {
00268
00269
ast_io_remove(ioc, ioc->
ior[x].
id);
00270 }
00271 }
00272 ioc->
current_ioc = -1;
00273 }
00274 }
00275
if (ioc->
needshrink)
00276 io_shrink(ioc);
00277 }
00278
return res;
00279 }
00280
00281 void ast_io_dump(
struct io_context *ioc)
00282 {
00283
00284
00285
00286
00287
int x;
00288
ast_log(
LOG_DEBUG,
"Asterisk IO Dump: %d entries, %d max entries\n", ioc->
fdcnt, ioc->
maxfdcnt);
00289
ast_log(
LOG_DEBUG,
"================================================\n");
00290
ast_log(
LOG_DEBUG,
"| ID FD Callback Data Events |\n");
00291
ast_log(
LOG_DEBUG,
"+------+------+-----------+-----------+--------+\n");
00292
for (x=0;x<ioc->
fdcnt;x++) {
00293
ast_log(
LOG_DEBUG,
"| %.4d | %.4d | %p | %p | %.6x |\n",
00294 *ioc->
ior[x].
id,
00295 ioc->
fds[x].
fd,
00296 ioc->
ior[x].
callback,
00297 ioc->
ior[x].
data,
00298 ioc->
fds[x].
events);
00299 }
00300
ast_log(
LOG_DEBUG,
"================================================\n");
00301 }
00302
00303
00304
00305 int ast_hide_password(
int fd)
00306 {
00307
struct termios tios;
00308
int res;
00309
int old;
00310
if (!isatty(fd))
00311
return -1;
00312 res = tcgetattr(fd, &tios);
00313
if (res < 0)
00314
return -1;
00315 old = tios.c_lflag & (ECHO | ECHONL);
00316 tios.c_lflag &= ~ECHO;
00317 tios.c_lflag |= ECHONL;
00318 res = tcsetattr(fd, TCSAFLUSH, &tios);
00319
if (res < 0)
00320
return -1;
00321
return old;
00322 }
00323
00324 int ast_restore_tty(
int fd,
int oldstate)
00325 {
00326
int res;
00327
struct termios tios;
00328
if (oldstate < 0)
00329
return 0;
00330 res = tcgetattr(fd, &tios);
00331
if (res < 0)
00332
return -1;
00333 tios.c_lflag &= ~(ECHO | ECHONL);
00334 tios.c_lflag |= oldstate;
00335 res = tcsetattr(fd, TCSAFLUSH, &tios);
00336
if (res < 0)
00337
return -1;
00338
return 0;
00339 }
00340
00341 int ast_get_termcols(
int fd)
00342 {
00343
struct winsize win;
00344
int cols = 0;
00345
00346
if (!isatty(fd))
00347
return -1;
00348
00349
if ( ioctl(fd, TIOCGWINSZ, &win) != -1 ) {
00350
if ( !cols && win.ws_col > 0 )
00351 cols = (
int) win.ws_col;
00352 }
else {
00353
00354 cols = 80;
00355 }
00356
00357
return cols;
00358 }
00359