Added initial inter-process communication: Sharing pids between processes.
[wsti_so.git] / src / process1.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 /* open/read/write/close */
6 #include <fcntl.h>
7
8 /* Signals handling.. */
9 #include <signal.h>
10
11 #include <sys/shm.h>
12
13
14 /** If buffer is too small to hold entire string, it is incremented by this value */
15 #define BUFFER_STEP 16
16
17 /** Buffer used to store line of characters */
18 char * buffer = NULL;
19
20 /** Named pipe used to communnicate with process2 */
21 char * write_pipe = "/tmp/process1pipe";
22
23 /** File descriptor of pipe */
24 int file_descriptor;
25
26
27 /**
28  * Shared memory variables
29  */
30 /**
31  * Memory key for processes. Must be same between all processes to properly
32  * communicate.
33  */
34 key_t shmkey = 18912;
35 /**
36  * Id of the shared memory
37  */
38 int shmid;
39
40 /**
41  * Message shared by processes. Contains array of process IDs
42  */
43 struct message {
44         pid_t pids[3];
45 };
46
47 struct message * processes = NULL;
48
49 /**
50  * Handler for signals.
51  */
52 void sig_handler(int signo)
53 {
54         fprintf(stderr, "[%s] Received %s!\n", "process1", strsignal(signo));
55         if (signo == SIGUSR1) {
56         }
57         else if (signo == SIGTERM) {
58                 int i = 0;
59                 fprintf(stderr, "[%s] > Releasing resources\n", "process1");
60                 close(write_pipe);
61                 unlink(write_pipe);
62
63                 if (buffer) {
64                         free(buffer);
65                         buffer = NULL;
66                 }
67                 for (; i < 3; i++) {
68                         fprintf(stderr, "[%s] Process %d, PID: %d\n", "process3", i, processes->pids[i]);
69                 }
70                 exit(0);
71         }
72         else if (signo == SIGTSTP) {
73                 fprintf(stderr, "[%s] > Closing pipe\n", "process1");
74                 close(write_pipe);
75                 raise (SIGSTOP);
76         }
77         else if (signo == SIGCONT) {
78                 fprintf(stderr, "[%s] > Opening pipe\n", "process1");
79                 file_descriptor = open(write_pipe, O_WRONLY);
80         }
81 }
82
83 /**
84  * Program reads entire lines of text from the standard input and pass them
85  * to the process2 using created pipe.
86  */
87 int main(void) {
88         /** Currently fetched from stdin character */
89         int c;
90
91         /** Current buffer length*/
92         int buffer_length = 0;
93
94         /** Index of the current character */
95         int i = 0;
96
97         /**
98          * Temporary buffer used as a proxy between
99          * checking memory allocation and copying data to real buffer 
100          */
101         char * tmp = NULL;
102
103         fprintf(stderr, "[%s] Init!\n", "process1");
104
105         /**
106          * Register signals handled by process
107          */
108         if (signal(SIGUSR1, sig_handler) == SIG_ERR) {
109                 fprintf(stderr, "can't catch SIGUSR1\n");
110         }
111         if (signal(SIGTERM, sig_handler) == SIG_ERR) {
112                 fprintf(stderr, "can't catch SIGTERM\n");
113         }
114         if (signal(SIGTSTP, sig_handler) == SIG_ERR) {
115                 fprintf(stderr, "can't catch SIGTSTP\n");
116         }
117         if (signal(SIGCONT, sig_handler) == SIG_ERR) {
118                 fprintf(stderr, "can't catch SIGCONT\n");
119         }
120
121         /*
122          * Register memory to share with other processes, and pass current
123          * process id to the array.
124          */
125         shmid = shmget(shmkey, sizeof(struct message), IPC_CREAT | 0666);
126
127         processes = (struct message *)shmat(shmid, NULL, 0);
128         processes->pids[0] = getpid();
129
130         mkfifo(write_pipe, 0666);
131
132         file_descriptor = open(write_pipe, O_WRONLY);
133
134         do {
135                 c = fgetc(stdin);
136
137                 /*
138                  * Check if current index is bigger than current buffer size.
139                  * If so increment buffer size. On error release memory, and set
140                  * appropriate flags.
141                  */
142                 if (i >= buffer_length) {
143                         tmp = NULL;
144                         buffer_length += BUFFER_STEP;
145                         tmp = (char*) realloc(buffer, buffer_length);
146                         if (tmp == NULL) {
147                                 fprintf(stderr, "[%s] Memory allocation problem on read!\n", "process1");
148                                 free(buffer);
149                                 buffer = NULL;
150                                 c = EOF;
151                         }
152                 }
153
154                 /*
155                  * If there were no errors or it was not just an empty newline:
156                  * parse data.
157                  */
158                 if (c != EOF || ((i == 0) && (c == 10))) {
159                         /* If newline has been found
160                          * return entire string and release the memory
161                          */
162                         if (c == 10 && (i != 0)) {
163                                 buffer[i] = '\n';
164                                 write(file_descriptor, buffer, strlen(buffer));
165                                 fprintf(stderr, "[%s] buffer: %s/%d\n", "process1", buffer, strlen(buffer));
166
167                                 buffer_length = 0;
168                                 i = 0;
169
170                                 free(buffer);
171                                 buffer = NULL;
172                                 tmp = NULL;
173                         }
174                         /*
175                          * Normal character, add it to the buffer
176                          */
177                         else {
178                                 buffer = tmp;
179                                 buffer[i] = c;
180
181                                 /* Used only for debugging..*/
182                                 /*
183                                 printf("c: %c/%d, i: %d, bl: %d\n", c, c, i, buffer_length);
184                                 */
185                                 i++;
186                         }
187                 }
188         } while(c != EOF);
189
190         /* Release resources in normal program flow exit. */
191         close(write_pipe);
192         unlink(write_pipe);
193
194         if (buffer) {
195                 free(buffer);
196                 buffer = NULL;
197         }
198
199         return 0;
200 }