static dbus_bool_t socket_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int flags) { DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; _dbus_assert (watch == socket_transport->read_watch || watch == socket_transport->write_watch); _dbus_assert (watch != NULL); /* If we hit an error here on a write watch, don't disconnect the transport yet because data can * still be in the buffer and do_reading may need several iteration to read * it all (because of its max_bytes_read_per_iteration limit). */ if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags)) { _dbus_verbose ("Hang up or error on watch\n"); _dbus_transport_disconnect (transport); return TRUE; } if (watch == socket_transport->read_watch && (flags & DBUS_WATCH_READABLE)) { dbus_bool_t auth_finished; #if 1 _dbus_verbose ("handling read watch %p flags = %x\n", watch, flags); #endif if (!do_authentication (transport, TRUE, FALSE, &auth_finished)) return FALSE; /* We don't want to do a read immediately following * a successful authentication. This is so we * have a chance to propagate the authentication * state further up. Specifically, we need to * process any pending data from the auth object. */ if (!auth_finished) { if (!do_reading (transport)) { _dbus_verbose ("no memory to read\n"); return FALSE; } } else { _dbus_verbose ("Not reading anything since we just completed the authentication\n"); } } else if (watch == socket_transport->write_watch && (flags & DBUS_WATCH_WRITABLE)) { #if 1 _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n", _dbus_connection_has_messages_to_send_unlocked (transport->connection)); #endif if (!do_authentication (transport, FALSE, TRUE, NULL)) return FALSE; if (!do_writing (transport)) { _dbus_verbose ("no memory to write\n"); return FALSE; } /* See if we still need the write watch */ check_write_watch (transport); } #ifdef DBUS_ENABLE_VERBOSE_MODE else { if (watch == socket_transport->read_watch) _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n", flags); else if (watch == socket_transport->write_watch) _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n", flags); else _dbus_verbose ("asked to handle watch %p on fd %" DBUS_SOCKET_FORMAT " that we don't recognize\n", watch, dbus_watch_get_socket (watch)); } #endif /* DBUS_ENABLE_VERBOSE_MODE */ return TRUE; }
int main(int argc, char *argv[]) { fd_set rfds; /* the structure for the select call */ int code; /* return code from system calls */ char out_buff[MAXLINE]; /* from child and stdin */ int out_flag[MAXLINE] ; /* initialize the output flags */ char *program; /* a string to hold the child program invocation */ char **pargs = 0; /* holds parts of the command line */ int not_command = 1; /* a flag while parsing the command line */ /* try to get a pseudoterminal to play with */ if (ptyopen(&contNum, &serverNum, controllerPath, serverPath) == -1) { perror("ptyopen failed"); exit(-1); } /* call the routine that handles signals */ catch_signals(); /* parse the command line arguments - as with the aixterm the command argument -e should be last on the line. */ while(*++argv && not_command) { if(!strcmp(*argv, "-f")) load_wct_file(*++argv); else if(!strcmp(*argv, "-e")) { not_command = 0; pargs = ++argv; } else { fprintf(stderr, "usage: clef [-f fname] -e command\n"); exit(-1); } } skim_wct(); #ifdef log sprintf(logpath, "/tmp/cleflog%d", getpid()); logfd = open(logpath, O_CREAT | O_RDWR, 0666); #endif /* get the original termio settings, so the child has them */ if(tcgetattr(0,&childbuf) == -1) { perror("clef trying to get the initial terminal settings"); exit(-1); } /* start the child process */ child_pid = fork(); switch(child_pid) { case -1 : perror("clef can't create a new process"); exit(-1); case 0: /* CHILD */ /* Dissasociate form my parents group so all my child processes look at my terminal as the controlling terminal for the group */ setsid(); serverNum = open(serverPath,O_RDWR); if (serverNum == -1) perror("open serverPath failed"); /* since I am the child, I can close ptc, and dup pts for all it standard descriptors */ if (dup2(serverNum, 0) == -1) perror("dup2 0 failed"); if (dup2(serverNum, 1) == -1) perror("dup2 1 failed"); if (dup2(serverNum, 2) == -1) perror("dup2 2 failed"); if( (dup2(serverNum, 0) == -1) || (dup2(serverNum, 1) == -1) || (dup2(serverNum, 2) == -1) ) { perror("clef trying to dup2"); exit(-1); } /* since they have been duped, close them */ close(serverNum); close(contNum); /* To make sure everything is nice, set off enhedit */ /* childbuf.c_line = 0; */ /* reconfigure the child's terminal get echoing */ if(tcsetattr(0, TCSAFLUSH, &childbuf) == -1) { perror("clef child trying to set child's terminal"); exit(-1); } /* fire up the child's process */ if(pargs){ execvp( pargs[0], pargs); perror("clef trying to execvp its argument"); fprintf(stderr, "Process --> %s\n", pargs[0]); } else{ program = getenv("SHELL"); if (!program) program = strdup("/bin/sh"); else program = strdup (program); execlp( program,program, 0); perror("clef trying to execlp the default child"); fprintf(stderr, "Process --> %s\n", program); } exit(-1); break; /* end switch */ } /* PARENT */ /* Since I am the parent, I should start to initialize some stuff. I have to close the pts side for it to work properly */ close(serverNum); ppid = getppid(); /* Iinitialize some stuff for the reading and writing */ init_flag(out_flag, MAXLINE); define_function_keys(); init_reader(); PTY = 1; init_parent(); /* Here is the main loop, it simply starts reading characters from the std input, and from the child. */ while(1) { /* loop forever */ /* use select to see who has stuff waiting for me to handle */ /* set file descriptors for ptc and stdin */ FD_ZERO(&rfds); FD_SET(contNum,&rfds); FD_SET(0,&rfds); set_function_chars(); #ifdef log { char modepath[30]; sprintf(modepath, "\nMODE = %d\n", MODE); write(logfd, modepath, strlen(modepath)); } #endif #ifdef logterm { struct termio ptermio; char pbuff[1024]; tcgetattr(contNum, &ptermio); sprintf(pbuff, "child's settings: Lflag = %d, Oflag = %d, Iflag = %d\n", ptermio.c_lflag, ptermio.c_oflag, ptermio.c_iflag); write(logfd, pbuff, strlen(pbuff)); } #endif code = select(FD_SETSIZE,(void *) &rfds, NULL, NULL, NULL); for(; code < 0 ;) { if(errno == EINTR) { check_flip(); code = select(FD_SETSIZE,(void *) &rfds, NULL, NULL, NULL); } else { perror("clef select failure"); exit(-1); } } /* reading from the child **/ if( FD_ISSET(contNum,&rfds)) { if( (num_read = read(contNum, out_buff, MAXLINE)) == -1) { num_read = 0; } #ifdef log write(logfd, "OUT<<<<<", strlen("OUT<<<<<")); write(logfd, out_buff, num_read); #endif if(num_read > 0) { /* now do the printing to the screen */ if(MODE!= CLEFRAW) { back_up(buff_pntr); write(1,out_buff, num_read); print_whole_buff(); /* reprint the input buffer */ } else write(1,out_buff, num_read); } } /* done the child stuff */ /* I should read from std input */ else { if(FD_ISSET(0,&rfds)) { num_read = read(0, in_buff, MAXLINE); #ifdef log write(logfd, "IN<<<<<", strlen("IN<<<<<")); write(logfd, in_buff, num_read); #endif check_flip(); if(MODE == CLEFRAW ) write(contNum, in_buff, num_read); else do_reading(); } } } }
/** * @todo We need to have a way to wake up the select sleep if * a new iteration request comes in with a flag (read/write) that * we're not currently serving. Otherwise a call that just reads * could block a write call forever (if there are no incoming * messages). */ static void socket_do_iteration (DBusTransport *transport, unsigned int flags, int timeout_milliseconds) { DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; DBusPollFD poll_fd; int poll_res; int poll_timeout; _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %" DBUS_SOCKET_FORMAT "\n", flags & DBUS_ITERATION_DO_READING ? "read" : "", flags & DBUS_ITERATION_DO_WRITING ? "write" : "", timeout_milliseconds, socket_transport->read_watch, socket_transport->write_watch, _dbus_socket_printable (socket_transport->fd)); /* the passed in DO_READING/DO_WRITING flags indicate whether to * read/write messages, but regardless of those we may need to block * for reading/writing to do auth. But if we do reading for auth, * we don't want to read any messages yet if not given DO_READING. */ poll_fd.fd = _dbus_socket_get_pollable (socket_transport->fd); poll_fd.events = 0; if (_dbus_transport_try_to_authenticate (transport)) { /* This is kind of a hack; if we have stuff to write, then try * to avoid the poll. This is probably about a 5% speedup on an * echo client/server. * * If both reading and writing were requested, we want to avoid this * since it could have funky effects: * - both ends spinning waiting for the other one to read * data so they can finish writing * - prioritizing all writing ahead of reading */ if ((flags & DBUS_ITERATION_DO_WRITING) && !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) && !transport->disconnected && _dbus_connection_has_messages_to_send_unlocked (transport->connection)) { do_writing (transport); if (transport->disconnected || !_dbus_connection_has_messages_to_send_unlocked (transport->connection)) goto out; } /* If we get here, we decided to do the poll() after all */ _dbus_assert (socket_transport->read_watch); if (flags & DBUS_ITERATION_DO_READING) poll_fd.events |= _DBUS_POLLIN; _dbus_assert (socket_transport->write_watch); if (flags & DBUS_ITERATION_DO_WRITING) poll_fd.events |= _DBUS_POLLOUT; } else { DBusAuthState auth_state; auth_state = _dbus_auth_do_work (transport->auth); if (transport->receive_credentials_pending || auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT) poll_fd.events |= _DBUS_POLLIN; if (transport->send_credentials_pending || auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND) poll_fd.events |= _DBUS_POLLOUT; } if (poll_fd.events) { int saved_errno; if (flags & DBUS_ITERATION_BLOCK) poll_timeout = timeout_milliseconds; else poll_timeout = 0; /* For blocking selects we drop the connection lock here * to avoid blocking out connection access during a potentially * indefinite blocking call. The io path is still protected * by the io_path_cond condvar, so we won't reenter this. */ if (flags & DBUS_ITERATION_BLOCK) { _dbus_verbose ("unlock pre poll\n"); _dbus_connection_unlock (transport->connection); } again: poll_res = _dbus_poll (&poll_fd, 1, poll_timeout); saved_errno = _dbus_save_socket_errno (); if (poll_res < 0 && _dbus_get_is_errno_eintr (saved_errno)) goto again; if (flags & DBUS_ITERATION_BLOCK) { _dbus_verbose ("lock post poll\n"); _dbus_connection_lock (transport->connection); } if (poll_res >= 0) { if (poll_res == 0) poll_fd.revents = 0; /* some concern that posix does not guarantee this; * valgrind flags it as an error. though it probably * is guaranteed on linux at least. */ if (poll_fd.revents & _DBUS_POLLERR) do_io_error (transport); else { dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0; dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0; dbus_bool_t authentication_completed; _dbus_verbose ("in iteration, need_read=%d need_write=%d\n", need_read, need_write); do_authentication (transport, need_read, need_write, &authentication_completed); /* See comment in socket_handle_watch. */ if (authentication_completed) goto out; if (need_read && (flags & DBUS_ITERATION_DO_READING)) do_reading (transport); if (need_write && (flags & DBUS_ITERATION_DO_WRITING)) do_writing (transport); } } else { _dbus_verbose ("Error from _dbus_poll(): %s\n", _dbus_strerror (saved_errno)); } } out: /* We need to install the write watch only if we did not * successfully write everything. Note we need to be careful that we * don't call check_write_watch *before* do_writing, since it's * inefficient to add the write watch, and we can avoid it most of * the time since we can write immediately. * * However, we MUST always call check_write_watch(); DBusConnection code * relies on the fact that running an iteration will notice that * messages are pending. */ check_write_watch (transport); _dbus_verbose (" ... leaving do_iteration()\n"); }
void handle_function_key(int key,int chann) { /** this procedure simply adds the string specified by the function key to the buffer ****/ int count, fd; int amount = strlen(function_key[key].str); int id; int save_echo; /*** This procedure takes the character at in_buff[num_proc] and adds it to the buffer. It first checks to see if we should be inserting or overwriting, and then does the appropriate thing *******/ switch ((function_key[key]).type) { case IMMEDIATE: if (INS_MODE) { forwardcopy(&buff[curr_pntr + amount], &buff[curr_pntr], buff_pntr - curr_pntr); forwardflag_cpy(&buff_flag[curr_pntr + amount], &buff_flag[curr_pntr], buff_pntr - curr_pntr); for (count = 0; count < amount; count++) { buff[curr_pntr + count] = (function_key[key].str)[count]; buff_flag[curr_pntr + count] = '1'; } ins_print(curr_pntr, amount + 1); buff_pntr = buff_pntr + amount; } else { for (count = 0; count < amount; count++) { buff[curr_pntr + count] = (function_key[key].str)[count]; buff_flag[curr_pntr + count] = '1'; myputchar((function_key[key].str)[count]); } } num_proc = num_proc + 6; curr_pntr = curr_pntr + amount; buff_pntr = buff_pntr + amount; send_function_to_child(); break; case DELAYED: if (INS_MODE) { forwardcopy(&buff[curr_pntr + amount], &buff[curr_pntr], buff_pntr - curr_pntr); forwardflag_cpy(&buff_flag[curr_pntr + amount], &buff_flag[curr_pntr], buff_pntr - curr_pntr); for (count = 0; count < amount; count++) { buff[curr_pntr + count] = (function_key[key].str)[count]; buff_flag[curr_pntr + count] = '1'; } ins_print(curr_pntr, amount + 1); buff_pntr = buff_pntr + amount; } else { for (count = 0; count < amount; count++) { buff[curr_pntr + count] = (function_key[key].str)[count]; buff_flag[curr_pntr + count] = '1'; myputchar((function_key[key].str)[count]); } } num_proc = num_proc + 6; curr_pntr = curr_pntr + amount; buff_pntr = buff_pntr + amount; fflush(stdout); break; case SPECIAL: /* fprintf(stderr, "Here I am \n"); */ if (access(editorfilename, F_OK) < 0) { fd = open(editorfilename, O_RDWR | O_CREAT, 0666); write(fd, buff, buff_pntr); back_up(buff_pntr); close(fd); } else { if (buff_pntr > 0) { fd = open(editorfilename, O_RDWR | O_TRUNC); write(fd, buff, buff_pntr); back_up(buff_pntr); close(fd); } } #if defined(MACOSXplatform) || defined(BSDplatform) bsdSignal(SIGCHLD, null_fnct,RestartSystemCalls); #else bsdSignal(SIGCLD, null_fnct,RestartSystemCalls); #endif switch (id = fork()) { case -1: perror("Special key"); break; case 0: execlp((function_key[12]).str, (function_key[12]).str, editorfilename, NULL); perror("Returned from exec"); exit(0); } while (wait((int *) 0) < 0); /** now I should read that file and send all it stuff thru the reader *****/ fd = open(editorfilename, O_RDWR); if (fd == -1) { perror("Opening temp file"); exit(-1); } num_proc += 6; /** reinitialize the buffer ***/ init_flag(buff_flag, buff_pntr); init_buff(buff, buff_pntr); /** reinitialize my buffer pointers **/ buff_pntr = curr_pntr = 0; /** reset the ring pointer **/ current = NULL; save_echo = ECHOIT; ECHOIT = 0; while ((num_read = read(fd, in_buff, MAXLINE))) { do_reading(); } close(fd); break; } return; }