📄 message.c
字号:
/* * It is possible that a client that requested some asynchronous processing * via xwaves has died before the request was satisfied. In this case, * xwaves will crash and burn if an attempt is made to use the stale handle. * This routine attempts to detect corruption is the structure that would * indicate abandonment. Not a sure thing, but better than nothing... */static intsanity_check(xs) Win_data *xs;{ return (xs && ((Window) xs->caller != None));}/*************************************************************************/do_ipc_response_if_any(xs, resp) Win_data *xs; char *resp;{ if (sanity_check(xs)) { if (resp && *resp) strcpy(out, resp); else strcpy(out, null); if (!Send_X_Reply(X_Display, NULL, xs->caller, xs->serial, out, strlen(out))) { sprintf(notice_msg, "Problems in %s sending completion IPC response(%s).", thisprog, pout); show_notice(1,notice_msg); } }}/*************************************************************************/static Notify_valueprocess_d_q(){ StrList *dq2; stop_d_clock(5471420); while (dq) { if (debug_level) fprintf(stderr, "%s dispatching IPC request:%s\n", thisprog, dq->str); this_request = dq; strcpy(out, exec_waves(dq->str)); if (dq->data && dq->data->caller) { pout = out; if (dq->data->tk) { /* if caller is TK, removed "returned" */ if (!strncmp("returned", out, 8)) { pout += 9; } } if (!Send_X_Reply(X_Display, NULL, dq->data->caller, dq->data->serial, pout, strlen(pout))) { sprintf(notice_msg, "Problems in %s sending delayed IPC response(%s).", thisprog, out); show_notice(1,notice_msg); } } pout = out; /* just in case somebody assumes that it == * out */ this_request = NULL; free(dq->str); free(dq->data); dq2 = dq->next; free(dq); dq = dq2; } if (under_xview) return (NOTIFY_DONE);}/*************************************************************************//* * Messages may have come in before an "attachment" was fully connected. This * is called when the attachment is complete and transfers those pending * requests to the xwaves dispatch queue from which they are sent to the * relevant attachment. */transfer_to_dispatch_q(l) StrList *l;{ if (l) { StrList *dqp = dq; if (dqp) { while (dqp->next) dqp = dqp->next; dqp->next = l; } else dq = l; }}/*************************************************************************/StrList *new_disp_ent(str) char *str;{ StrList *q; if (str && *str && (q = (StrList *) malloc(sizeof(StrList)))) { q->str = str; q->next = NULL; q->data = NULL; return (q); } return (NULL);}/*************************************************************************//* * In most cases, it is preferable to defer processing of incoming xwaves * commands until after the IPC dispatch process is complete. This places * commands that can be handled this way on the queue. */static char *delay_dispatch(str, data) char *str; void *data;{ if (str && *str) { StrList *dqp, *qp2; if ((dqp = new_disp_ent(savestring(str)))) { dqp->data = data; if (!dq) dq = dqp; else { qp2 = dq; while (qp2->next) qp2 = qp2->next; qp2->next = dqp; } restart_d_clock(10000, 5471420, process_d_q); return (ok); } else fprintf(stderr, "%s: Allocation failure in delay_dispatch()\n", thisprog); } return (null);}/*************************************************************************//* * Run any program as a background job. "command_line" holds the full * command to be backgrounded. One use for this is to start "attachments". */background_a_program(command_line) char *command_line;{ char *args[5]; int pid; /* set execvp args */ args[0] = "/bin/sh"; args[1] = "-c"; args[2] = command_line; args[3] = "&"; args[4] = NULL; /* Fork a new process to run the command. */#if defined(SUN4) || defined(SUN3) || defined(DS3100) switch (pid = vfork()) {#else switch (pid = fork()) {#endif case -1: /* fork failed */ perror("background_a_program; fork failed"); return (FALSE); case 0: /* child process */ setpgrp(0, getpid()); execvp(args[0], args); perror("background_a_program: execvp failed"); return (FALSE); default: /* parent */ return (TRUE); }}/*************************************************************************/free_list(l) StrList *l;{ StrList *l2; while (l) { if (l->str) { free(l->str); } l2 = l->next; free(l); l = l2; }}/*************************************************************************//* * This is the main IPC dispatch procedure. It returns immediately or after * completion of the actual request, depending on the value of "procedure * number" used in the clnt_call() issued by the client program. Unless * absolutely necessary (e.g. to obtain data) the client call should specify * IMMEDIATE RESPONSE which permits asynchronous processing of the request. */static voiddispatch_ipc(dest, caller, serial, req, in) char *dest; Window caller; int serial; int req; char *in;{ int res; if (debug_level) fprintf(stderr, "%s got an IPC request(%s)\n", thisprog, in); if (in && *in) { switch (req) { case RPCINFO_CALL: fprintf(stderr, "Program %s Lives!\n", thisprog); strcpy(out, "all's well"); break; default: fprintf(stderr, "Unrecognized req in %s IPC dispatch\n", thisprog); case IMMEDIATE_RESPONSE: strcpy(out, delay_dispatch(in, NULL)); break; case INTERLOCK_RESPONSE: case INTERLOCK_NOREPLY: strcpy(out, exec_waves(in)); break; case INTERLOCK_DELAY_RESPONSE: { Win_data *xptr = (Win_data *) (malloc(sizeof(Win_data))); xptr->caller = caller; xptr->serial = serial; xptr->tk = 0; delay_dispatch(in, xptr); return; } case INTERLOCK_DELAY_RESPONSE_TK: { Win_data *xptr = (Win_data *) (malloc(sizeof(Win_data))); xptr->caller = caller; xptr->serial = serial; xptr->tk = 1; /* this signals that the caller is TK */ /* It causes the "returned" to be removed */ delay_dispatch(in, xptr); return; } } } else { fprintf(stderr, "Null request in %s IPC dispatch\n", thisprog); strcpy(out, null); } if (req != INTERLOCK_NOREPLY && caller) if (!Send_X_Reply(X_Display, NULL, caller, serial, out, strlen(out))) { sprintf(notice_msg, "Problems in %s sending IPC response(%s).", thisprog, pout); show_notice(1,notice_msg); } return;}static voidevent_proc(window, event, arg) Xv_Window window; Event *event; Notify_arg arg;{ XEvent *p; int ret; Window win; p = event->ie_xevent; win = (Window) xv_get(window, XV_XID); if (win == comm_window) Read_X_Comm(X_Display, win, p, 1, NULL, 1024, dispatch_ipc);}char *setup_ipc(frame, name) Frame frame; char *name;{ char *Setup_X_Comm(); X_Display = (Display *) xv_get(frame, XV_DISPLAY); comm_window = (Window) xv_get(frame, XV_XID); xv_set(frame, WIN_X_EVENT_MASK, NoEventMask, NULL); xv_set(frame, WIN_EVENT_PROC, event_proc, WIN_X_EVENT_MASK, PropertyChangeMask, NULL); return Setup_X_Comm(name, X_Display, comm_window);}/*************************************************************************/intsetup_attach_comm(frame, dest, myname) char *dest, *myname; Frame frame;{ Window Get_X_Comm_Win(); registry_name = setup_ipc(frame, myname); if (registry_name) { remote_name = dest; remote_comm_window = Get_X_Comm_Win(X_Display, dest); if (remote_comm_window == None) { show_notice(1, "setup_attach_comm: can't get remote comm window"); return 0; } } else show_notice(1, "setup_attach_comm: setup_ipc failed!"); return (registry_name != NULL);}voidsend_start_command(command) char *command;{ extern char *host; int res; sprintf(in, "%s start function %s registry %s command %s", host, thisprog, registry_name, command); res = Send_X_Msg(X_Display, remote_name, None, IMMEDIATE_RESPONSE, in, strlen(in)); if (!res) { sprintf(notice_msg, "Problem sending startup message:\n%s", in); show_notice(1,notice_msg); }}/*************************************************************************/terminate_communication(name) char *name;{ if (debug_level) fprintf(stderr, "terminate_communication()\n"); if (X_Display && name) { Close_X_Comm(X_Display, name); remote_name = NULL; }}/*************************************************************************/mess_write(str) char *str;{ return (mess_send(str, IMMEDIATE_RESPONSE));}/*************************************************************************/terminal_message(str) char *str;{ return (mess_send(str, INTERLOCK_NOREPLY));}/*************************************************************************/mess_send(str, type) char *str; int type;{ int res; if (remote_comm_window != None && str && *str) { res = Send_X_Msg(X_Display, remote_name, remote_comm_window, type, str, strlen(str)); if (!res) { if (debug_level) { fprintf(stderr, "mess_send failed on: %s\n", str); } return (FALSE); } return (TRUE); } else if (remote_comm_window == None) fprintf(stderr, "No attachments are registered; ignoring send request.\n"); else fprintf(stderr, "%s: bad args to mess_send()\n", thisprog); return (FALSE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -