]> git.somenet.org - pub/jan/sysprog.git/blob - forksort/forksort.c
all the old sysprog files
[pub/jan/sysprog.git] / forksort / forksort.c
1 /**************\r
2 * Name:    forksort.c\r
3 * Author:       Jan Vales (e0726236@student.tuwien.ac.at)\r
4 * Date:         13.1.2010\r
5 * Purpose:  Forksorting\r
6 * Usage:  forksort\r
7 * Input:  <lines to sort>\n<line>\n<line>\n...\r
8 * Output:  sorted input\r
9 **************/\r
10 #include "globals.h"\r
11 \r
12 char *szCommand = "";\r
13 \r
14 void usage(){\r
15   (void)fprintf(stderr, "Usage: %s\n", szCommand);\r
16   exit(EXIT_FAILURE); \r
17 }\r
18 \r
19 void bailout(const char *msgstr){\r
20   if(errno == 0) {\r
21     (void)fprintf(stderr, "%s(%d(%d)): [ERROR] %s\n", szCommand, getpid(), getppid(), msgstr);\r
22   }else{\r
23     (void)fprintf(stderr, "%s(%d(%d)): [ERROR(%d)] %s: %s\n", szCommand, getpid(), getppid(), errno, msgstr, strerror(errno));\r
24   }\r
25   exit(EXIT_FAILURE);\r
26 }\r
27 \r
28 void myTrim(char *str){\r
29   unsigned int c;\r
30   if(str == 0 || strlen(str) == 0) return;\r
31   while(isspace(str[0]))for(c=0; c<strlen(str); c++)str[c] = str[c+1];\r
32   for(c = strlen(str)-1; isspace(str[c]); c--)str[c] = 0;\r
33 }\r
34 \r
35 int readLine(char *lineRet, FILE *fp){\r
36   char tmpLine[MAX_CHARS];\r
37   if(fgets(tmpLine, MAX_CHARS, fp)==NULL) {\r
38 /*    (void)fprintf(stderr, "%s (pid %i): [DBG] readLine(): error at fgets, returning EOF\n", szCommand, getpid()); */\r
39     return EOF;\r
40   }\r
41   if((strlen(tmpLine) == (MAX_CHARS-1)) && (tmpLine[strlen(tmpLine)-1] != '\n'))while(fgetc(fp) != '\n');\r
42   myTrim(tmpLine);\r
43   strcpy(lineRet, tmpLine);\r
44   return EXIT_SUCCESS;\r
45 }\r
46 \r
47 \r
48 int main(int argc, char *argv[]){\r
49 fprintf(stderr, "%d \n", strcmp("aa","bb"));\r
50 fprintf(stderr, "%d \n", strcmp("bb","bb"));\r
51 \r
52 fprintf(stderr, "%d \n", strcmp("cc","bb"));\r
53 \r
54 \r
55 return 0;\r
56 \r
57   int linecnt;\r
58   char tmpLine[MAX_CHARS];\r
59   int i;\r
60 \r
61 /*\r
62 p2c = parent 2 child\r
63 c2p = child 2 parent\r
64 */\r
65 \r
66   int lPp2c[2];\r
67   int lPc2p[2];\r
68   FILE *lfp2c;\r
69   FILE *lfc2p;\r
70   pid_t lPid;\r
71   int lStat;\r
72 \r
73   int rPp2c[2];\r
74   int rPc2p[2];\r
75   FILE *rfp2c;\r
76   FILE *rfc2p;\r
77   pid_t rPid;\r
78   char tmpLineR[MAX_CHARS];\r
79   int rStat;\r
80 \r
81   szCommand = argv[0];\r
82   if(argc != 1)usage();\r
83 \r
84   if(readLine(tmpLine, stdin) == EOF)bailout("Cannot read Line");\r
85   if(sscanf(tmpLine, "%i", &linecnt) != 1)bailout("Cannot parse Line-Count");\r
86 \r
87   if(linecnt <= 0)bailout("Linecount must be positive!");\r
88   if(linecnt == 1){\r
89     readLine(tmpLine, stdin);\r
90     (void)fprintf(stdout, "%s\n", tmpLine);\r
91     return 0;\r
92   }\r
93 \r
94   /* only if linecnt >1: do stuff below this line */\r
95 \r
96   if(pipe(lPc2p) == EOF || pipe(lPp2c) == EOF)bailout("LC: Cannot create pipes");\r
97   if(pipe(rPc2p) == EOF || pipe(rPp2c) == EOF)bailout("Cannot create pipes for R child");\r
98 \r
99 \r
100   /*** MERGE-SORT::SPLIT DATA ***/\r
101   lPid = fork();\r
102   switch(lPid) {\r
103     case -1: bailout("error forking left child!");\r
104     case 0:\r
105       if((close(lPc2p[0]) < 0) || (close(lPp2c[1]) < 0))bailout("LC: Cannot close unneeded pipe ends");\r
106       if((dup2(lPc2p[1], fileno(stdout)) == EOF) || (dup2(lPp2c[0], fileno(stdin)) == EOF))bailout("LC: dup2 failed");\r
107       if(execlp(argv[0], argv[0], (const char*)0) < 0)bailout("LC: execlp() failed");\r
108       break;\r
109     default:\r
110       close(lPc2p[1]);\r
111       close(lPp2c[0]);\r
112       if((lfp2c = fdopen(lPp2c[1], "w")) == NULL)bailout("LC: fdopen(lPp2c[1]) failed");\r
113 \r
114       /* write stuff to left child's stdin */\r
115       if(fprintf(lfp2c, "%i\n", (linecnt/2)) < 0)bailout("LC: Cannot write linecnt.");\r
116       for(i = 0; i < (linecnt/2); i++){\r
117         if(readLine(tmpLine, stdin) == EOF)bailout("Cannot read stdin");\r
118         if(fprintf(lfp2c, "%s\n", tmpLine) < 0)bailout("LC: Cannot write to lfp2c");\r
119       }\r
120       if(fclose(lfp2c) == EOF)bailout("LC: fclose(lfp2c) failed");\r
121   }\r
122 \r
123   rPid = fork();\r
124   switch(rPid) {\r
125     case -1: bailout("error forking right child!");\r
126     case 0:\r
127       if((close(rPc2p[0]) < 0) || (close(rPp2c[1]) < 0))bailout("RC: Cannot close unneeded pipe ends");\r
128       if((dup2(rPc2p[1], fileno(stdout)) == EOF) || (dup2(rPp2c[0], fileno(stdin)) == EOF))bailout("RC: dup2 failed");\r
129       if(execlp(argv[0], argv[0], (const char*)0) < 0)bailout("RC: execlp() failed");\r
130       break;\r
131     default:\r
132       close(rPc2p[1]);\r
133       close(rPp2c[0]);\r
134       if((rfp2c = fdopen(rPp2c[1], "w")) == NULL)bailout("RC: fdopen(rPp2c[1]) failed");\r
135 \r
136       /* write stuff to left child's stdin */\r
137       if(fprintf(rfp2c, "%i\n", (linecnt-(linecnt/2))) < 0)bailout("RC: Cannot write linecnt.");\r
138       for(i = (linecnt/2); i < linecnt; i++) {\r
139         if(readLine(tmpLine, stdin) == EOF)bailout("Cannot read stdin");\r
140         if(fprintf(rfp2c, "%s\n", tmpLine) < 0)bailout("RC: Cannot write to rfp2c");\r
141       }\r
142 \r
143       if(fclose(rfp2c) == EOF)bailout("RC: fclose(rfp2c) failed");\r
144   }\r
145 \r
146   /*** MERGE-SORT::MERGE DATA ***/\r
147   if((lfc2p = fdopen(lPc2p[0], "r")) == NULL) bailout("fdopen(lPc2p[0], r)");\r
148   if((rfc2p = fdopen(rPc2p[0], "r")) == NULL) bailout("fdopen(rPc2p[0], r)");\r
149 \r
150   if((lStat = readLine(tmpLine, lfc2p)) == EXIT_FAILURE)bailout("LC: Cannot read results");\r
151   if((rStat = readLine(tmpLineR, rfc2p)) == EXIT_FAILURE)bailout("RC: Cannot read results");\r
152 \r
153   while(lStat != EOF || rStat != EOF) {\r
154 fprintf(stderr, "%d hier %d - %d\n", getpid(), lStat, rStat);\r
155 \r
156     if(lStat == EOF){\r
157       while(rStat != EOF) {\r
158         fprintf(stdout, "%s\n", tmpLineR);\r
159         if((rStat = readLine(tmpLineR, rfc2p)) == EXIT_FAILURE)bailout("RC: Cannot read results");\r
160       }\r
161 fprintf(stderr, "%d hier1 %d - %d\n", getpid(), lStat, rStat);\r
162 \r
163     }\r
164 \r
165     if(rStat == EOF) {\r
166       while(lStat != EOF) {\r
167         fprintf(stdout, "%s\n", tmpLine);\r
168         if((lStat = readLine(tmpLine, lfc2p)) == EXIT_FAILURE)bailout("LC: Cannot read results");\r
169       }\r
170 fprintf(stderr, "%d hier2 %d - %d\n", getpid(), lStat, rStat);\r
171 \r
172     }\r
173 \r
174     while((lStat != EOF && rStat != EOF) && (strcmp(tmpLine, tmpLineR) > 0)) {\r
175       fprintf(stdout, "%s\n", tmpLineR);\r
176       if((rStat = readLine(tmpLineR, rfc2p)) == EXIT_FAILURE)bailout("RC: Cannot read results");\r
177 fprintf(stderr, "%d hier3 %d - %d\n", getpid(), lStat, rStat);\r
178     }\r
179 \r
180     while((lStat != EOF && rStat != EOF) && (strcmp(tmpLine, tmpLineR) <= 0)) {\r
181       fprintf(stdout, "%s\n", tmpLine);\r
182       if((lStat = readLine(tmpLine, lfc2p)) == EXIT_FAILURE)bailout("LC: Cannot read results");\r
183 fprintf(stderr, "%d hier3 %d - %d\n", getpid(), lStat, rStat);\r
184     }\r
185 fprintf(stderr, "%d hier4 %d - %d\n", getpid(), lStat, rStat);\r
186   }\r
187 \r
188 fprintf(stderr, "%d hier5 %d - %d\n", getpid(), lStat, rStat);\r
189 \r
190   if(fclose(lfc2p) == EOF) return EXIT_FAILURE;\r
191   if(fclose(rfc2p) == EOF) return EXIT_FAILURE;\r
192 \r
193   waitpid(lPid, 0, 0);\r
194   waitpid(rPid, 0, 0);\r
195   return 0;\r
196 }\r
197 \r