WhiteBoard Project using C RPC
A Project in Distributed Computing at IIIT-Delhi
client.c
Go to the documentation of this file.
1 
2 /* client.c */
3 
4 #include "wb.h"
5 
6 /*
7  * A "white board client" is a pair of processes. The forked child
8  * receives server call-backs to callbackfromwbs() via its svc_run().
9  * The parent process will handle the xwindow I/O. These two
10  * write/read via the pipe xwinio.
11  */
12 
13 static int parentid, childid; /* process ids */
14 static int xwinio[2]; /* pipe: child writes, parent reads */
15 static AddLineArg me; /* all the info there is about this client */
16 static CLIENT *clp; /* librpc clnt_create()-ed */
17 
18 /*
19  * Terminate the client. Remove all traces of the parent+child
20  */
21 static void endtheclient(int unused)
22 {
23  delclient_1(&me.clientdata, clp); /* ask server to delete me */
24  clnt_destroy(clp); /* CLIENT structure */
25  pmap_unset(me.clientdata.nprogram, me.clientdata.nversion);
26  closexwindow();
27  kill(childid, SIGTERM);
28  exit(0);
29 }
30 
31 /*
32  * Get the call back from the server who is sending the coordinates of
33  * a line to draw. We simply write these four integers into the
34  * xwinio pipe, and raise the signal so the parent can read.
35  */
37 {
38  static int i = 0; /* note: static */
39 
40  write(xwinio[1], p, sizeof(OneLn));
41  kill(parentid, SIGUSR1); /* kill == "raise" */
42  return (void *) &i;
43 }
44 
45 /*
46  * Invoked via callbackfromwbs/SIGUSR1 when a new line comes from the
47  * server to the svc_run()-ning process.
48  */
49 static void readndraw(int unused)
50 {
51  OneLn lc;
52 
53  (void) read(xwinio[0], &lc, sizeof(lc));
54  drawline(&lc);
55 }
56 
57 /*
58  * Client window got exposed. Redraw the lines.
59  */
60 static void exposedwindow(CLIENT * clp)
61 {
62  Linep p, *q = sendallmylines_1(&me.clientdata, clp);
63  int n = 0;
64 
65  if (q == NULL)
66  return;
67  for (p = *q; p; p = p->next) {
68  drawline(&p->ln);
69  n++;
70  }
71 }
72 
73 /*
74  * Watch for mouse input. Button 3 (right) ends this routine.
75  * Pressing buttons 1 (left) or 2 (middle) sends the line to the
76  * server who will distribute it to all member white boards.
77  */
78 static void mousewatch(CLIENT * clp)
79 {
80  int btn = 5;
81 
82  for (;;)
83  switch (btn) {
84  case 1:
85  case 2:
86  me.ln.color = me.clientdata.color;
87  addline_1(&me, clp);
88  btn = 0;
89  break;
90  case 3:
91  return; /* <== */
92  case 5:
93  exposedwindow(clp);
94  btn = 0;
95  break;
96  default:
97  btn = trackpointer(&me.ln, 0);
98  break;
99  }
100 }
101 
102 /*
103  * Called by client_s.c. See ./ed-script. Start the client.
104  */
105 void startclient
106  (int nprogram, int nversion,
107  char *servermcnm, char *boardnm, char *xdisplaynm, char *pmcolor) {
108  /* clients own details -- once set, these do not change */
109  me.clientdata.color = atoir(pmcolor, 16);
110  me.clientdata.nprogram = nprogram;
111  me.clientdata.nversion = nversion;
112  gethostname(me.clientdata.machinenm, sizeof(me.clientdata.machinenm));
113  strcpy(me.clientdata.boardnm, boardnm);
114  strcpy(me.clientdata.xdisplaynm, xdisplaynm);
115  strcat(me.clientdata.xdisplaynm, ":0.0");
116 
117  char xwintitle[100];
118  sprintf(xwintitle, "%s@%s color=%lx",
119  boardnm, me.clientdata.machinenm, me.clientdata.color);
120 
121  clp = clnt_create
122  (servermcnm, WhiteBoardServer, WhiteBoardServerVersion, "tcp");
123  if (!clp) {
124  fprintf(stderr,
125  "client730: clnt_create(%s,0x%x,0x%x,%s) failed.\n",
126  servermcnm, WhiteBoardServer, WhiteBoardServerVersion, "tcp");
127  exit(1);
128  }
129 
130  if (pipe(xwinio) == -1) {
131  fprintf(stderr, "client730: xindow io pipe failed.\n");
132  exit(2);
133  }
134 
135  childid = fork();
136  if (childid == -1) {
137  fprintf(stderr, "client730: fork was unsuccessful.\n");
138  exit(3);
139  }
140  if (childid == 0) {
141  /* the child process */
142  close(xwinio[0]);
143  parentid = getppid();
144  return; /* child returns to do svc_run() */
145  }
146 
147  /* parent process continues */
148 
149  { /* setup signal handling */
150  struct sigaction asigterm, asiguser;
151  asigterm.sa_handler = endtheclient;
152  asigterm.sa_flags = 0;
153  sigemptyset(&asigterm.sa_mask);
154  sigaction(SIGTERM, &asigterm, 0);
155 
156  asiguser.sa_handler = readndraw;
157  asiguser.sa_flags = 0;
158  sigemptyset(&asiguser.sa_mask);
159  sigaction(SIGUSR1, &asiguser, 0);
160  }
161 
162  close(xwinio[1]);
163  int x = openxwindow(me.clientdata.xdisplaynm, xwintitle);
164  if (x < 0) {
165  fprintf(stderr, "client730: openxwindow(%s, %s) == %d, failed\n",
166  me.clientdata.xdisplaynm, xwintitle, x);
167  exit(4);
168  }
169 
170  addclient_1(&me.clientdata, clp);
171  mousewatch(clp); /* returns only when button3 is clicked */
172  endtheclient(0);
173 }
174 
175 /* -eof- */
Definition: oneln.h:2
static CLIENT * clp
Definition: client.c:16
int sigemptyset(sigset_t *set)
int sigaction(int, const struct sigaction *, struct sigaction *)
static int childid
Definition: client.c:13
long atoir(char *p, int r)
Definition: xwindow.c:163
static AddLineArg me
Definition: client.c:15
int gethostname(char *name, size_t len)
static void endtheclient(int unused)
Definition: client.c:21
int pmap_unset(unsigned long, unsigned long)
int openxwindow(char *, char *)
void startclient(int nprogram, int nversion, char *servermcnm, char *boardnm, char *xdisplaynm, char *pmcolor)
Definition: client.c:106
static void readndraw(int unused)
Definition: client.c:49
int sa_flags
Definition: wb.h:33
void(* sa_handler)(int)
Definition: wb.h:30
static void exposedwindow(CLIENT *clp)
Definition: client.c:60
static void mousewatch(CLIENT *clp)
Definition: client.c:78
void closexwindow()
Definition: xwindow.c:73
static int xwinio[2]
Definition: client.c:14
static int parentid
Definition: client.c:13
int kill(pid_t pid, int sig)
Definition: wb.h:28
sigset_t sa_mask
Definition: wb.h:32
void drawline(void *)
int trackpointer(void *, int)
void * callbackfromwbs_1_svc(OneLn *p)
Definition: client.c:36