io.c File Reference

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <termios.h>
#include <string.h>
#include <sys/ioctl.h>
#include <asterisk/io.h>
#include <asterisk/logger.h>

Include dependency graph for io.c:

Go to the source code of this file.

Data Structures

struct  io_rec
struct  io_context

Defines

#define DEBUG(a)
#define GROW_SHRINK_SIZE   512

Functions

struct io_contextio_context_create (void)
 Creates a context.
void io_context_destroy (struct io_context *ioc)
 Destroys a context.
int * ast_io_add (struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
 Adds an IO context.
int * ast_io_change (struct io_context *ioc, int *id, int fd, ast_io_cb callback, short events, void *data)
 Changes an IO handler.
int ast_io_remove (struct io_context *ioc, int *_id)
 Removes an IO context.
int ast_io_wait (struct io_context *ioc, int howlong)
 Waits for IO.
void ast_io_dump (struct io_context *ioc)
 Dumps the IO array.
int ast_hide_password (int fd)
 Set fd into non-echoing mode (if fd is a tty).
int ast_restore_tty (int fd, int oldstate)
 Restores TTY mode.
int ast_get_termcols (int fd)


Define Documentation

#define DEBUG (  ) 

Definition at line 26 of file io.c.

#define GROW_SHRINK_SIZE   512

Definition at line 45 of file io.c.


Function Documentation

int ast_get_termcols ( int  fd  ) 

Definition at line 341 of file io.c.

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       /* assume 80 characters if the ioctl fails for some reason */
00354       cols = 80;
00355    }
00356 
00357    return cols;
00358 }

int ast_hide_password ( int  fd  ) 

Set fd into non-echoing mode (if fd is a tty).

Definition at line 305 of file io.c.

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 }

int* ast_io_add ( struct io_context ioc,
int  fd,
ast_io_cb  callback,
short  events,
void *  data 
)

Adds an IO context.

Parameters:
ioc which context to use
fd which fd to monitor
callback callback function to run
events event mask of events to wait for
data data to pass to the callback Watch for any of revents activites on fd, calling callback with data as callback data. Returns a pointer to ID of the IO event, or NULL on failure.

Definition at line 139 of file io.c.

00140 {
00141    /*
00142     * Add a new I/O entry for this file descriptor
00143     * with the given event mask, to call callback with
00144     * data as an argument.  Returns NULL on failure.
00145     */
00146    int *ret;
00147    DEBUG(ast_log(LOG_DEBUG, "ast_io_add()\n"));
00148    if (ioc->fdcnt >= ioc->maxfdcnt) {
00149       /* 
00150        * We don't have enough space for this entry.  We need to
00151        * reallocate maxfdcnt poll fd's and io_rec's, or back out now.
00152        */
00153       if (io_grow(ioc))
00154          return NULL;
00155    }
00156 
00157    /*
00158     * At this point, we've got sufficiently large arrays going
00159     * and we can make an entry for it in the pollfd and io_r
00160     * structures.
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    /* Bonk if we couldn't allocate an int */
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 }

int* ast_io_change ( struct io_context ioc,
int *  id,
int  fd,
ast_io_cb  callback,
short  events,
void *  data 
)

Changes an IO handler.

Parameters:
ioc which context to use
id 
fd the fd you wish it to contain now
callback new callback function
events event mask to wait for
data data to pass to the callback function Change an i/o handler, updating fd if > -1, callback if non-null, and revents if >-1, and data if non-null. Returns a pointero to the ID of the IO event, or NULL on failure.

Definition at line 176 of file io.c.

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 }

void ast_io_dump ( struct io_context ioc  ) 

Dumps the IO array.

Definition at line 281 of file io.c.

00282 {
00283    /*
00284     * Print some debugging information via
00285     * the logger interface
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 }

int ast_io_remove ( struct io_context ioc,
int *  id 
)

Removes an IO context.

Parameters:
ioc which io_context to remove it from
id which ID to remove Remove an I/O id from consideration Returns 0 on success or -1 on failure.

Definition at line 218 of file io.c.

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          /* Free the int immediately and set to NULL so we know it's unused now */
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 }

int ast_io_wait ( struct io_context ioc,
int  howlong 
)

Waits for IO.

Parameters:
ioc which context to act upon
howlong how many milliseconds to wait Wait for I/O to happen, returning after howlong milliseconds, and after processing any necessary I/O. Returns the number of I/O events which took place.

Definition at line 243 of file io.c.

00244 {
00245    /*
00246     * Make the poll call, and call
00247     * the callbacks for anything that needs
00248     * to be handled
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        * At least one event
00258        */
00259       origcnt = ioc->fdcnt;
00260       for(x=0;x<origcnt;x++) {
00261          /* Yes, it is possible for an entry to be deleted and still have an
00262             event waiting if it occurs after the original calling id */
00263          if (ioc->fds[x].revents && ioc->ior[x].id) {
00264             /* There's an event waiting */
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                   /* Time to delete them since they returned a 0 */
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 }

int ast_restore_tty ( int  fd,
int  oldstate 
)

Restores TTY mode.

Definition at line 324 of file io.c.

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 }

struct io_context* io_context_create ( void   )  [read]

Creates a context.

Create a context for I/O operations Basically mallocs an IO structure and sets up some default values. Returns an allocated io_context structure

Definition at line 65 of file io.c.

00066 {
00067    /* Create an I/O context */
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 }

void io_context_destroy ( struct io_context ioc  ) 

Destroys a context.

Definition at line 93 of file io.c.

00094 {
00095    /* Free associated memory with an I/O context */
00096    if (ioc->fds)
00097       free(ioc->fds);
00098    if (ioc->ior)
00099       free(ioc->ior);
00100    free(ioc);
00101 }


Generated on Wed Oct 28 17:00:56 2009 for Asterisk by  doxygen 1.5.6