static const char *readline(void) { ssize_t count; char *p_read = NULL; char *p_eol = NULL; char *ret = NULL; struct atcontext *ac = getAtContext(); read(ac->fd,NULL,0); /* This is a little odd. I use *s_ATBufferCur == 0 to mean * "buffer consumed completely". If it points to a character, * then the buffer continues until a \0. */ if (*ac->ATBufferCur == '\0') { /* Empty buffer. */ ac->ATBufferCur = ac->ATBuffer; *ac->ATBufferCur = '\0'; p_read = ac->ATBuffer; } else { /* *s_ATBufferCur != '\0' */ /* There's data in the buffer from the last read. */ /* skip over leading newlines */ while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n') ac->ATBufferCur++; p_eol = findNextEOL(ac->ATBufferCur); if (p_eol == NULL) { /* A partial line. Move it up and prepare to read more. */ size_t len; len = strlen(ac->ATBufferCur); memmove(ac->ATBuffer, ac->ATBufferCur, len + 1); p_read = ac->ATBuffer + len; ac->ATBufferCur = ac->ATBuffer; } /* Otherwise, (p_eol !- NULL) there is a complete line that will be returned from the while () loop below. */ } while (p_eol == NULL) { int err; struct pollfd pfds[2]; /* This condition should be synchronized with the read function call * size argument below. */ if (0 >= MAX_AT_RESPONSE - (p_read - ac->ATBuffer) - 2) { ALOGE("%s() ERROR: Input line exceeded buffer", __func__); /* Ditch buffer and start over again. */ ac->ATBufferCur = ac->ATBuffer; *ac->ATBufferCur = '\0'; p_read = ac->ATBuffer; } /* If our fd is invalid, we are probably closed. Return. */ if (ac->fd < 0) return NULL; pfds[0].fd = ac->fd; pfds[0].events = POLLIN | POLLERR; pfds[1].fd = ac->readerCmdFds[0]; pfds[1].events = POLLIN; err = poll(pfds, 2, -1); if (err < 0) { ALOGE("%s() poll: error: %s", __func__, strerror(errno)); return NULL; } if (pfds[1].revents & POLLIN) { char buf[10]; /* Just drain it. We don't care, this is just for waking up. */ read(pfds[1].fd, &buf, 1); continue; } if (pfds[0].revents & POLLERR) { ALOGE("%s() POLLERR event! Returning...", __func__); return NULL; } if (!(pfds[0].revents & POLLIN)) continue; do /* The size argument should be synchronized to the ditch buffer * condition above. */ count = read(ac->fd, p_read, MAX_AT_RESPONSE - (p_read - ac->ATBuffer) - 2); while (count < 0 && errno == EINTR); if (count > 0) { AT_DUMP( "<< ", p_read, count ); ac->readCount += count; /* Implementation requires extra EOS or EOL to get it right if * there are no trailing newlines in the read buffer. Adding extra * EOS does not harm even if there actually were trailing EOLs. */ p_read[count] = '\0'; p_read[count+1] = '\0'; /* Skip over leading newlines. */ while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n') ac->ATBufferCur++; p_eol = findNextEOL(ac->ATBufferCur); p_read += count; } else if (count <= 0) { /* Read error encountered or EOF reached. */ if (count == 0) ALOGD("%s() atchannel: EOF reached.", __func__); else ALOGD("%s() atchannel: read error %s", __func__, strerror(errno)); return NULL; } } /* A full line in the buffer. Place a \0 over the \r and return. */ ret = ac->ATBufferCur; *p_eol = '\0'; /* The extra EOS added after read takes care of the case when there is no * valid data after p_eol. */ ac->ATBufferCur = p_eol + 1; /* This will always be <= p_read, and there will be a \0 at *p_read. */ ALOGI("AT(%d)< %s", ac->fd, ret); return ret; }
static const char *readline() { ssize_t count; char *p_read = NULL; char *p_eol = NULL; char *ret; /* this is a little odd. I use *s_ATBufferCur == 0 to * mean "buffer consumed completely". If it points to a character, than * the buffer continues until a \0 */ if (*s_ATBufferCur == '\0') { /* empty buffer */ s_ATBufferCur = s_ATBuffer; *s_ATBufferCur = '\0'; p_read = s_ATBuffer; } else { /* *s_ATBufferCur != '\0' */ /* there's data in the buffer from the last read */ // skip over leading newlines while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') s_ATBufferCur++; p_eol = findNextEOL(s_ATBufferCur); if (p_eol == NULL) { /* a partial line. move it up and prepare to read more */ size_t len; len = strlen(s_ATBufferCur); memmove(s_ATBuffer, s_ATBufferCur, len + 1); p_read = s_ATBuffer + len; s_ATBufferCur = s_ATBuffer; } /* Otherwise, (p_eol !- NULL) there is a complete line */ /* that will be returned the while () loop below */ } while (p_eol == NULL) { if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) { LOGE("ERROR: Input line exceeded buffer\n"); /* ditch buffer and start over again */ s_ATBufferCur = s_ATBuffer; *s_ATBufferCur = '\0'; p_read = s_ATBuffer; } do { count = read(s_fd, p_read, MAX_AT_RESPONSE - (p_read - s_ATBuffer)); } while (count < 0 && errno == EINTR); if (count > 0) { AT_DUMP( "<< ", p_read, count ); s_readCount += count; p_read[count] = '\0'; // skip over leading newlines while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') s_ATBufferCur++; p_eol = findNextEOL(s_ATBufferCur); p_read += count; } else if (count <= 0) { /* read error encountered or EOF reached */ if(count == 0) { LOGD("atchannel: EOF reached"); } else { LOGD("atchannel: read error %s", strerror(errno)); } return NULL; } } /* a full line in the buffer. Place a \0 over the \r and return */ ret = s_ATBufferCur; *p_eol = '\0'; s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */ /* and there will be a \0 at *p_read */ LOGD("AT< %s\n", ret); return ret; }
static const char *readline(void) { ssize_t count; char *p_read = NULL; char *p_eol = NULL; char *ret = NULL; struct atcontext *context = get_at_context(); ENTER; read(context->fd,NULL,0); /* This is a little odd. I use *s_ATBufferCur == 0 to mean * "buffer consumed completely". If it points to a character, * then the buffer continues until a \0. */ if (*context->ATBufferCur == '\0') { /* Empty buffer. */ context->ATBufferCur = context->ATBuffer; *context->ATBufferCur = '\0'; p_read = context->ATBuffer; } else { /* *s_ATBufferCur != '\0' */ /* There's data in the buffer from the last read. */ /* skip over leading newlines */ while (*context->ATBufferCur == '\r' || *context->ATBufferCur == '\n') context->ATBufferCur++; p_eol = findNextEOL(context->ATBufferCur); if (p_eol == NULL) { /* A partial line. Move it up and prepare to read more. */ size_t len; len = strlen(context->ATBufferCur); memmove(context->ATBuffer, context->ATBufferCur, len + 1); p_read = context->ATBuffer + len; context->ATBufferCur = context->ATBuffer; } /* Otherwise, (p_eol !- NULL) there is a complete line that will be returned from the while () loop below. */ } while (p_eol == NULL) { int err; struct pollfd pfds[2]; if (0 >= MAX_AT_RESPONSE - (p_read - context->ATBuffer)) { MBMLOGE("%s() ERROR: Input line exceeded buffer", __FUNCTION__); /* Ditch buffer and start over again. */ context->ATBufferCur = context->ATBuffer; *context->ATBufferCur = '\0'; p_read = context->ATBuffer; } /* If our fd is invalid, we are probably closed. Return. */ if (context->fd < 0) { EXIT; return NULL; } pfds[0].fd = context->fd; pfds[0].events = POLLIN | POLLERR; pfds[1].fd = context->readerCmdFds[0]; pfds[1].events = POLLIN; err = poll(pfds, 2, -1); if (err < 0) { MBMLOGE("%s() poll: error: %s", __FUNCTION__, strerror(errno)); EXIT; return NULL; } if (pfds[1].revents & POLLIN) { char buf[10]; /* Just drain it. We don't care, this is just for waking up. */ read(pfds[1].fd, &buf, 1); continue; } if (pfds[0].revents & POLLERR) { MBMLOGE("POLLERR! Returning.."); EXIT; return NULL; } if (!(pfds[0].revents & POLLIN)) { continue; } do { count = read(context->fd, p_read, MAX_AT_RESPONSE - (p_read - context->ATBuffer)); } while (count < 0 && ((errno == EINTR) || (errno == EAGAIN))); if (count > 0) { AT_DUMP( "<< ", p_read, count ); context->readCount += count; p_read[count] = '\0'; /* Skip over leading newlines. */ while (*context->ATBufferCur == '\r' || *context->ATBufferCur == '\n') context->ATBufferCur++; p_eol = findNextEOL(context->ATBufferCur); p_read += count; } else if (count <= 0) { /* Read error encountered or EOF reached. */ if (count == 0) { MBMLOGE("%s() atchannel: EOF reached.", __FUNCTION__); } else { MBMLOGE("%s() atchannel: read error %s", __FUNCTION__, strerror(errno)); } EXIT; return NULL; } } /* A full line in the buffer. Place a \0 over the \r and return. */ ret = context->ATBufferCur; *p_eol = '\0'; context->ATBufferCur = p_eol + 1; /* This will always be <= p_read, and there will be a \0 at *p_read. */ MBMLOGD("AT(%d)< %s", context->fd, ret); EXIT; return ret; }