38
39 /*
40 * Process the data
41 */
42 operation = request->operation;
43 switch (operation) {
44 case REQ_QUIT:
45 break;
46 case REQ_READ:
47 if (strlen (request->prompt) > 0)
48 printf (request->prompt);
49 if (fgets (request->text, 128, stdin) == NULL)
50 request->text[0] = ' ';
51 /*
52 * Because fgets returns the newline, and we don't
53 * want it, we look for it, and turn it into a null
54 * (truncating the input) if found. It should be the
55 * last character, if it is there.
56 */
57 len = strlen (request->text);
58 if (len > 0 && request->text[len-l] == '
')
59 request->text[len-l] = ' ';
60 break;
61 case REQ_WRITE:
62 puts (request->text);
63 break;
64 default:
65 break;
66 }
67 if (request->synchronous) {
68 status = pthread_mutex_lock (&tty_server.mutex);
69 if (status != 0)
70 err_abort (status, 'Lock server mutex');
71 request->done_flag = 1;
72 status = pthread_cond_signal (&request->done);
73 if (status != 0)
74 err_abort (status, 'Signal server condition');
75 status = pthread_mutex_unlock (&tty_server.mutex);
76 if (status != 0)
77 err_abort (status, 'Unlock server mutex');
78 } else
79 free (request);
80 if (operation == REQ_QUIT)
81 break;
82 }
83 return NULL;
84 }
Part 3 shows the function that is called to initiate a request to the tty server thread. The caller specifies the desired operation (REQ_QUIT, REQ_READ, or REQ_ WRITE), whether the operation is synchronous or not (sync), an optional prompt string (prompt) for REQ_READ operations, and the pointer to a string (input for REQ_WRITE, or a buffer to return the result of an REQ_READ operation).
16-40 If a tty server thread is not already running, start one. A temporary thread attributes object (detached_attr) is created, and the
45-76 Allocate and initialize a server request (request_t) packet. If the request is synchronous, initialize the condition variable (done) in the request packet — otherwise the condition variable isn't used. The new request is linked onto the request queue.
81-83 Wake the server thread to handle the queued request.
88-105 If the request is synchronous, wait for the server to set done_flag and signal the done condition variable. If the operation is REQ_READ, copy the result string into the output buffer. Finally, destroy the condition variable, and free the request packet.
¦ server.c part 3 tty_server_request
1 /*
2 * Request an operation
3 */
4 void tty_server_request (
5 int operation,
6 int sync,
7 const char *prompt,
8 char *string)
9 {
10 request_t *request;
11 int status;
12
13 status = pthread_mutex_lock (&tty_server.mutex);
14 if (status != 0)
15 err_abort (status, 'Lock server mutex');
16 if (!tty_server.running) {
17 pthread_t thread;
18 pthread_attr_t detached_attr;
19
20 status = pthread_attr_init (&detached_attr);
21 if (status != 0)
22 err_abort (status, 'Init attributes object');
23 status = pthread_attr_setdetachstate (
24 &detached_attr, PTHREAD_CREATE_DETACHED);
25 if (status != 0)
26 err_abort (status, 'Set detach state');
27 tty_server.running = 1;
28 status = pthread_create (&thread, &detached_attr,
29 tty_server_routine, NULL);
30 if (status != 0)
31 err_abort (status, 'Create server');
32
33 /*
34 * Ignore an error in destroying the attributes object.
35 * It's unlikely to fail, there's nothing useful we can
36 * do about it, and it's not worth aborting the program