static char *recvline() { char *line, *start, *end; size_t r; size_t remain = BUFFER_SIZE - buffer->used; if (buffer->used > 0) { start = buffer->data; end = (char *)memchr((void *)start, '\n', buffer->used); if (end) { /* Found a newline */ *end = '\0'; /* Replace newline with null to return */ r = end - start; line = estrndup(start, r); buffer->used -= r + 1; start = end + 1; memmove(buffer->data, start, buffer->used); trim_in_place(line); return line; } else if (remain == 0) { fprintf(stderr, "Fatal: Line exceeds buffer length\n"); global_exit(0); } } if (remain > 0) { r = recv(sockfd, (buffer->data+buffer->used), remain, 0); if (r == -1) { perror("recv"); global_exit(1); } else if (r == 0) { fprintf(stderr,"Server dropped connection.\n"); global_exit(1); } buffer->used += r; return recvline(); } }
char *snreadline(char *buffer, size_t length, char *prompt) { char *line; if (batch_f) { line = fgets(buffer, length, stdin); } else { line = readline(prompt); } if (line == NULL) return line; trim_in_place(line); if (batch_f) return line; size_t linelen = strlen(line); if (linelen > 0) add_history(line); size_t copy = linelen > length-1 ? length-1 : linelen; memcpy(buffer, line, copy); buffer[copy] = '\0'; free(line); return buffer; }
int main(int argc, char **argv) { program_name = basename(argv[0]); snprintf(doc,DOC_BUFFER_LEN,"%s -- a simple client for COMP-535",program_name); struct arguments arguments; /* Default values. */ arguments.port = -1; arguments.host = NULL; arguments.adaptive = 0; arguments.verbose = 0; arguments.silent = 0; arguments.batch = 0; arguments.devnull = 0; arguments.infile = NULL; argp_parse (&argp, argc, argv, 0, 0, &arguments); verbose_f = 0; if (arguments.verbose) verbose_f = 1; if (arguments.silent) { freopen("/dev/null", "w", stderr); freopen("/dev/null", "w", stdout); } batch_f = arguments.batch; adaptive_f = arguments.adaptive; if (arguments.infile) { if(freopen(arguments.infile, "r", stdin) == NULL){ exit(1); } } sockfd = -1; if (adaptive_f) adaptivefd = -1; signal(SIGINT, interrupt); char foldertmp[] = "clientimgXXXXXX"; char s[INET6_ADDRSTRLEN], *t, *line, linebuf[LINE_SIZE]; char *filename, *filebuf; int cid, l; /* Return values, temp values */ FILE *file; size_t filesize, read, remain, total, chunk; sockfd = connect_to_host(arguments.host, arguments.port, s, sizeof s); if (sockfd == -1) { fprintf(stderr, "failed to connect to server.\n"); global_exit(1); } fprintf(stdout, "Connected to %s\n", s); buffer = ALLOC(readbuffer); buffer->used = 0; // HELLO YES THIS IS SERVER line = recvline(); t = strtok(line,DELIM); if (strcmp(t, "HELLO") != 0){ fprintf(stderr,"Unexpected message from server: %s\nExiting.\n", line); global_exit(0); } t = strtok(NULL,DELIM); cid = (int)strtol(t,NULL,0); if (errno == ERANGE) { /* Not a number? or number too big? */ fprintf(stderr, "Invalid client ID from server. Exiting"); global_exit(1); } fprintf(stdout, "Got client ID: %d\n", cid); if (adaptive_f) { if ((t = strtok(NULL,DELIM)) == NULL){ fprintf(stderr, "Server is not in adaptive mode. Exiting\n"); global_exit(1); } errno = 0; l = (int)strtol(t,NULL,0); if (errno == ERANGE) { /* Not a number? or number too big? */ fprintf(stderr, "Invalid port number from server. Exiting"); global_exit(1); } adaptivefd = connect_to_host(arguments.host, l, NULL, 0); if (adaptivefd == -1) { fprintf(stderr, "failed to connect to adaptive server.\n"); global_exit(2); } snprintf(linebuf, LINE_SIZE, "%d\n", cid); if (send(adaptivefd, linebuf, strlen(linebuf), 0) == -1){ perror("send"); global_exit(1); } } efree(line); if (!arguments.devnull){ mkdtemp(foldertmp); fprintf(stdout, "Storing downloaded images in directory %s.\n", foldertmp); } for (;;) { #ifdef HAS_GNUREADLINE if(snreadline(linebuf, LINE_SIZE, "GET> ") == NULL){ #else if (!batch_f) fprintf(stderr, "GET> "); if(fgets(linebuf, LINE_SIZE, stdin) == NULL){ #endif printf("exit\n"); global_exit(0); } #ifndef HAS_GNUREADLINE trim_in_place(linebuf); #endif if (strlen(linebuf) == 0) continue; /* Hacky hack to transmit panning speed, any 2 or less digit number is considered a pan speed */ if (adaptive_f && strlen(linebuf) < 3 && is_number(linebuf)) { add_newline(linebuf, LINE_SIZE); if (send(adaptivefd, linebuf, strlen(linebuf), 0) == -1){ perror("send"); global_exit(1); } continue; } if (add_newline(linebuf, LINE_SIZE)) { fprintf(stderr, "Command too long.\n"); continue; } if (send(sockfd, linebuf, strlen(linebuf), 0) == -1){ perror("send"); global_exit(1); } remove_newline(linebuf); line = recvline(); t = strtok(line,DELIM); if (strcmp(t, "ERROR") == 0){ t = strtok(NULL,DELIM); fprintf(stderr, "Server> Error: %s\n", t); } else if (strcmp(t, "FILE") == 0) { t = strtok(NULL,DELIM); errno = 0; size_t filesize = (size_t)strtol(t,NULL,0); if (errno == ERANGE) { fprintf(stderr,"Fatal Error: Could not parse file size.\n", t); global_exit(0); } if (!arguments.devnull) { l = snprintf(NULL, 0, "%s/%s", foldertmp, linebuf); filename = (char *)emalloc(l+1); snprintf(filename, l+1, "%s/%s", foldertmp, linebuf); } else { filename = (char *)emalloc(10); snprintf(filename, 10, "/dev/null"); } file = fopen(filename,"wb"); efree(filename); chunk = (filesize > MAX_FILE_BUFFER) ? MAX_FILE_BUFFER : filesize; filebuf = (char *)emalloc(chunk); remain = filesize; total = 0; if (buffer->used > 0){ fwrite(buffer->data, 1, buffer->used, file); total += buffer->used; remain -= buffer->used; buffer->used = 0; } fprintf(stderr,"'%s' [%ld/%ld] (%ld%%)", linebuf, (long)total, (long)filesize, (long)(100*total)/filesize); while (remain > 0) { read = recv(sockfd, filebuf, chunk, 0); if (read == -1) { perror("recv"); global_exit(3); } else if (read == 0) { fprintf(stderr,"Server dropped connection.\n"); global_exit(4); } total += read; remain -= read; fprintf(stderr,"%c[2K\r", 27); fprintf(stderr,"'%s' [%ld/%ld] (%ld%%)", linebuf, (long)total, (long)filesize, (long)(100*total)/filesize); fwrite(filebuf, 1, read, file); } fprintf(stderr,"%c[2K\r", 27); printf("'%s' saved. [%ld/%ld]\n", linebuf, (long)total, (long)filesize); fclose(file); efree(filebuf); } else { verbose("Ignoring unexpected message from server: %s\n", t); } efree(line); } }
static void prvInterpreterDaemon(void* pvParameters) { char c; char buffer[32]; char* cmd; int abort, size; vTaskDelay(1000); vUartPuts("\r\n"); for (;;) { abort = 0; size = 0; vUartPuts(prompt); vUartPuts(" # "); buffer[0] = 0; while ((c = cUartGetc())) { if (size == 32) { abort = 1; vUartPuts("\r\nerror: command too long...\r\n"); break; } if (c == '\r' || c == '\n') { vUartPuts("\r\n"); buffer[size] = 0; break; } else if (c == 0x03) { abort = 1; vUartPuts("\r\n"); buffer[size] = 0; vUartPuts(buffer); vUartPuts(": abort\r\n"); break; } else if (c == 0x08 || c == 0x7f) { if (size > 0) { size--; vUartPutc(c); vUartPutc(' '); vUartPutc(c); } continue; } else if (!is_letter(c) && !is_number(c) && !is_space(c) && c != '-' && c != ':' && c != '.') continue; vUartPutc(c); buffer[size++] = c; } if (abort) continue; cmd = trim_in_place(buffer); // Skip empty command if (cmd[0] == 0) continue; abort = 1; for (int i = 0; i < n_tokens; i++) { if (cmd[0] == tokens[i].command) { (*tokens[i].handler)(cmd + 1); abort = 0; vUartPuts("\r\n"); break; } } if (abort) { vUartPuts("error: undefined command '"); vUartPutc(cmd[0]); vUartPuts("\r\n"); } } }