41e0ea4729508bc71bcdb70f7cf423ace48942f3
[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  * Message queue variables
51  */
52 key_t qkey;
53 int qid_input;
54
55 int qid_output1;
56 int qid_output2;
57
58 struct queue_message {
59         int signo;
60 };
61
62 /**
63  * Handler for signals.
64  */
65 void sig_handler(int signo)
66 {
67         fprintf(stderr, "[%s] Received %s!\n", "process1", strsignal(signo));
68         if (signo == SIGUSR1) {
69                 fprintf(stderr, "[%s] > Notified!\n", "process3");
70         }
71         else if (signo == SIGTERM) {
72                 int i = 0;
73                 struct queue_message msg;
74                 msg.signo = signo;
75
76                 fprintf(stderr, "[%s] > Releasing resources\n", "process1");
77                 close(write_pipe);
78                 unlink(write_pipe);
79
80                 if (buffer) {
81                         free(buffer);
82                         buffer = NULL;
83                 }
84                 for (; i < 3; i++) {
85                         pid_t pid = processes->pids[i];
86                         fprintf(stderr, "[%s] Process %d, PID: %d\n", "process3", i, pid);
87                         // Bleh
88                         if (i != 0) {
89                                 msgsnd(pid, &msg, sizeof(msg));
90                                 kill(pid, SIGUSR1);
91                         }
92                 }
93                 exit(0);
94         }
95         else if (signo == SIGTSTP) {
96                 fprintf(stderr, "[%s] > Closing pipe\n", "process1");
97                 close(write_pipe);
98                 raise (SIGSTOP);
99         }
100         else if (signo == SIGCONT) {
101                 fprintf(stderr, "[%s] > Opening pipe\n", "process1");
102                 file_descriptor = open(write_pipe, O_WRONLY);
103         }
104 }
105
106 /**
107  * Program reads entire lines of text from the standard input and pass them
108  * to the process2 using created pipe.
109  */
110 int main(void) {
111         /** Currently fetched from stdin character */
112         int c;
113
114         /** Current buffer length*/
115         int buffer_length = 0;
116
117         /** Index of the current character */
118         int i = 0;
119
120         /**
121          * Temporary buffer used as a proxy between
122          * checking memory allocation and copying data to real buffer 
123          */
124         char * tmp = NULL;
125
126         fprintf(stderr, "[%s] Init!\n", "process1");
127
128         /**
129          * Register signals handled by process
130          */
131         if (signal(SIGUSR1, sig_handler) == SIG_ERR) {
132                 fprintf(stderr, "can't catch SIGUSR1\n");
133         }
134         if (signal(SIGTERM, sig_handler) == SIG_ERR) {
135                 fprintf(stderr, "can't catch SIGTERM\n");
136         }
137         if (signal(SIGTSTP, sig_handler) == SIG_ERR) {
138                 fprintf(stderr, "can't catch SIGTSTP\n");
139         }
140         if (signal(SIGCONT, sig_handler) == SIG_ERR) {
141                 fprintf(stderr, "can't catch SIGCONT\n");
142         }
143
144         /*
145          * Register memory to share with other processes, and pass current
146          * process id to the array.
147          */
148         shmid = shmget(shmkey, sizeof(struct message), IPC_CREAT | 0666);
149
150         processes = (struct message *)shmat(shmid, NULL, 0);
151         processes->pids[0] = getpid();
152
153         fprintf(stderr, "[%s] Shared pid: %d\n", "process1", getpid());
154
155         sleep(1);
156         /**
157          * Register message queue to communicate with other processes
158          */
159         qkey = getpid();
160         qid_input = msgget(qkey, IPC_CREAT | 0666);
161         
162         qid_output1 = msgget(processes->pids[1], IPC_CREAT | 0666);
163         qid_output2 = msgget(processes->pids[2], IPC_CREAT | 0666);
164         
165         mkfifo(write_pipe, 0666);
166
167         file_descriptor = open(write_pipe, O_WRONLY);
168
169         do {
170                 c = fgetc(stdin);
171
172                 /*
173                  * Check if current index is bigger than current buffer size.
174                  * If so increment buffer size. On error release memory, and set
175                  * appropriate flags.
176                  */
177                 if (i >= buffer_length) {
178                         tmp = NULL;
179                         buffer_length += BUFFER_STEP;
180                         tmp = (char*) realloc(buffer, buffer_length);
181                         if (tmp == NULL) {
182                                 fprintf(stderr, "[%s] Memory allocation problem on read!\n", "process1");
183                                 free(buffer);
184                                 buffer = NULL;
185                                 c = EOF;
186                         }
187                 }
188
189                 /*
190                  * If there were no errors or it was not just an empty newline:
191                  * parse data.
192                  */
193                 if (c != EOF || ((i == 0) && (c == 10))) {
194                         /* If newline has been found
195                          * return entire string and release the memory
196                          */
197                         if (c == 10 && (i != 0)) {
198                                 buffer[i] = '\n';
199                                 write(file_descriptor, buffer, strlen(buffer));
200                                 fprintf(stderr, "[%s] buffer: %s/%d\n", "process1", buffer, strlen(buffer));
201
202                                 buffer_length = 0;
203                                 i = 0;
204
205                                 free(buffer);
206                                 buffer = NULL;
207                                 tmp = NULL;
208                         }
209                         /*
210                          * Normal character, add it to the buffer
211                          */
212                         else {
213                                 buffer = tmp;
214                                 buffer[i] = c;
215
216                                 /* Used only for debugging..*/
217                                 /*
218                                 printf("c: %c/%d, i: %d, bl: %d\n", c, c, i, buffer_length);
219                                 */
220                                 i++;
221                         }
222                 }
223         } while(c != EOF);
224
225         /* Release resources in normal program flow exit. */
226         close(write_pipe);
227         unlink(write_pipe);
228
229         if (buffer) {
230                 free(buffer);
231                 buffer = NULL;
232         }
233
234         return 0;
235 }