/* * Our child has snuffed it. check if it was an editor, and update the * session list if that is the case. */ void sig_chld_bottomhalf __P0 (void) { int fd, pid, ret; editsess **sp, *p; /* GH: while() instead of just one check */ while ((pid = waitpid(-1, &ret, WNOHANG)) > 0) { /* GH: check for WIFSTOPPED unnecessary since no */ /* WUNTRACED to waitpid() */ for (sp = &edit_sess; *sp && (*sp)->pid != pid; sp = &(*sp)->next) ; if (*sp) { finish_edit(*sp); p = *sp; *sp = p->next; fd = p->fd; free(p->descr); free(p->file); free(p); /* GH: only send message if found matching session */ /* send the edit_end message if this is the last editor... */ if ((!edit_sess) && (*edit_end)) { int otcp_fd = tcp_fd; /* backup current socket fd */ tcp_fd = fd; error = 0; parse_instruction(edit_end, 0, 0, 1); history_done = 0; tcp_fd = otcp_fd; } } } }
void edit_end(player *p,char *str) { void (*fn)(); fn=p->edit_info->finish_func; (*fn)(p); finish_edit(p); }
/* finish editing with changes */ void edit_end(player * p, char *str) { (*p->edit_info->finish_func) (p); finish_edit(p); }
/* finish editing without changes */ void edit_quit(player * p, char *str) { (*p->edit_info->quit_func) (p); finish_edit(p); }
/* * start an editing session: process the EDIT/VIEW message * if view == 1, text will be viewed, else edited */ void message_edit __P4 (char *,text, int,msglen, char,view, char,builtin) { char tmpname[BUFSIZE], command_str[BUFSIZE], buf[BUFSIZE]; char *errdesc = "#warning: protocol error (message_edit, no %s)\n"; int tmpfd, i, childpid; unsigned int key; editsess *s; char *editor, *descr; char *args[4]; int waitforeditor; status(1); args[0] = "/bin/sh"; args[1] = "-c"; args[2] = command_str; args[3] = 0; if (view) { key = (unsigned int)-1; i = 0; } else { if (text[0] != 'M') { tty_printf(errdesc, "M"); free(text); return; } for (i = 1; i < msglen && isdigit(text[i]); i++) ; if (text[i++] != '\n' || i >= msglen) { tty_printf(errdesc, "\\n"); free(text); return; } key = strtoul(text + 1, NULL, 10); } descr = text + i; while (i < msglen && text[i] != '\n') i++; if (i >= msglen) { tty_printf(errdesc, "desc"); free(text); return; } text[i++] = '\0'; sprintf(tmpname, "/tmp/powwow.%u.%d%d", key, getpid(), abs(rand()) >> 8); if ((tmpfd = open(tmpname, O_WRONLY | O_CREAT, 0600)) < 0) { errmsg("create temp edit file"); free(text); return; } if (write(tmpfd, text + i, msglen - i) < msglen - i) { errmsg("write to temp edit file"); free(text); close(tmpfd); return; } close(tmpfd); s = (editsess*)malloc(sizeof(editsess)); if (!s) { errmsg("malloc"); return; } s->ctime = time((time_t*)NULL); s->oldsize = msglen - i; s->key = key; s->fd = (view || builtin) ? -1 : tcp_fd; /* MUME doesn't expect a reply. */ s->cancel = 0; s->descr = my_strdup(descr); s->file = my_strdup(tmpname); free(text); /* send a edit_start message (if wanted) */ if ((!edit_sess) && (*edit_start)) { error = 0; parse_instruction(edit_start, 0, 0, 1); history_done = 0; } if (view) { if (!(editor = getenv("POWWOWPAGER")) && !(editor = getenv("PAGER"))) editor = "more"; } else { if (!(editor = getenv("POWWOWEDITOR")) && !(editor = getenv("EDITOR"))) editor = "emacs"; } if (editor[0] == '&') { waitforeditor = 0; editor++; } else waitforeditor = 1; if (waitforeditor) { tty_quit(); /* ignore SIGINT since interrupting the child would interrupt us too, if we are in the same tty group */ sig_permanent(SIGINT, SIG_IGN); sig_permanent(SIGCHLD, SIG_DFL); } switch(childpid = fork()) { /* let's get schizophrenic */ case 0: sprintf(command_str, "%s %s", editor, s->file); sprintf(buf, "TITLE=%s", s->descr); putenv(buf); /* setenv("TITLE", s->descr, 1);*/ execvp((char *)args[0], (char **)args); syserr("execve"); break; case -1: errmsg("fork"); free(s->descr); free(s->file); free(s); return; } s->pid = childpid; if (waitforeditor) { while ((i = waitpid(childpid, (int*)NULL, 0)) == -1 && errno == EINTR) ; signal_start(); /* reset SIGINT and SIGCHLD handlers */ tty_start(); if (s->fd != -1) { tty_gotoxy(0, lines - 1); tty_putc('\n'); } if (i == -1) errmsg("waitpid"); else finish_edit(s); free(s->descr); free(s->file); if (i != -1 && !edit_sess && *edit_end) { error = 0; parse_instruction(edit_end, 0, 0, 1); history_done = 0; } free(s); } else { s->next = edit_sess; edit_sess = s; } }