File: server_8c-source.html

package info (click to toggle)
klone 1.1.1.dfsg1-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 6,480 kB
  • ctags: 4,238
  • sloc: ansic: 16,288; makefile: 384; sh: 351
file content (1351 lines) | stat: -rw-r--r-- 79,923 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>KLone: server.c Source File</title>
<link href="kl.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.9.1 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="annotated.html">Data&nbsp;Structures</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Data&nbsp;Fields</a> | <a class="qindex" href="globals.html">Globals</a></div>
<div class="nav">
<a class="el" href="dir_000000.html">src</a>&nbsp;/&nbsp;<a class="el" href="dir_000003.html">kloned</a></div>
<h1>server.c</h1><a href="server_8c.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment">00001 <span class="comment">/*</span>
00002 <span class="comment"> * Copyright (c) 2005, 2006 by KoanLogic s.r.l. &lt;http://www.koanlogic.com&gt;</span>
00003 <span class="comment"> * All rights reserved.</span>
00004 <span class="comment"> *</span>
00005 <span class="comment"> * This file is part of KLone, and as such it is subject to the license stated</span>
00006 <span class="comment"> * in the LICENSE file which you have received as part of this distribution.</span>
00007 <span class="comment"> *</span>
00008 <span class="comment"> * $Id: server.c,v 1.52 2006/05/27 16:34:01 tat Exp $</span>
00009 <span class="comment"> */</span>
00010 
00011 <span class="preprocessor">#include "klone_conf.h"</span>
00012 <span class="preprocessor">#include &lt;sys/types.h&gt;</span>
00013 <span class="preprocessor">#include &lt;sys/stat.h&gt;</span>
00014 <span class="preprocessor">#include &lt;sys/wait.h&gt;</span>
00015 <span class="preprocessor">#include &lt;u/libu.h&gt;</span>
00016 <span class="preprocessor">#include &lt;stdlib.h&gt;</span>
00017 <span class="preprocessor">#include &lt;unistd.h&gt;</span>
00018 <span class="preprocessor">#include &lt;errno.h&gt;</span>
00019 <span class="preprocessor">#include &lt;fcntl.h&gt;</span>
00020 <span class="preprocessor">#include &lt;<a class="code" href="server_8h.html">klone/server.h</a>&gt;</span>
00021 <span class="preprocessor">#include &lt;<a class="code" href="backend_8h.html">klone/backend.h</a>&gt;</span>
00022 <span class="preprocessor">#include &lt;<a class="code" href="os_8h.html">klone/os.h</a>&gt;</span>
00023 <span class="preprocessor">#include &lt;<a class="code" href="timer_8h.html">klone/timer.h</a>&gt;</span>
00024 <span class="preprocessor">#include &lt;<a class="code" href="context_8h.html">klone/context.h</a>&gt;</span>
00025 <span class="preprocessor">#include &lt;<a class="code" href="ppc_8h.html">klone/ppc.h</a>&gt;</span>
00026 <span class="preprocessor">#include &lt;<a class="code" href="ppc__cmd_8h.html">klone/ppc_cmd.h</a>&gt;</span>
00027 <span class="preprocessor">#include &lt;<a class="code" href="addr_8h.html">klone/addr.h</a>&gt;</span>
00028 <span class="preprocessor">#include &lt;<a class="code" href="utils_8h.html">klone/utils.h</a>&gt;</span>
00029 <span class="preprocessor">#include &lt;<a class="code" href="klog_8h.html">klone/klog.h</a>&gt;</span>
00030 <span class="preprocessor">#include "<a class="code" href="server__s_8h.html">server_s.h</a>"</span>
00031 <span class="preprocessor">#include "<a class="code" href="server__ppc__cmd_8h.html">server_ppc_cmd.h</a>"</span>
00032 <span class="preprocessor">#include "<a class="code" href="child_8h.html">child.h</a>"</span>
00033 
<a name="l00034"></a><a class="code" href="server_8c.html#a0">00034</a> <span class="preprocessor">#define SERVER_MAX_BACKENDS 8</span>
00035 <span class="preprocessor"></span>
<a name="l00036"></a><a class="code" href="server_8c.html#a33">00036</a> <span class="keyword">enum</span> <a class="code" href="server_8c.html#a33">watch_fd_e</a>
00037 {
00038     <a class="code" href="server_8c.html#a33a1">WATCH_FD_READ</a>   = 1 &lt;&lt; 1,
00039     <a class="code" href="server_8c.html#a33a2">WATCH_FD_WRITE</a>  = 1 &lt;&lt; 2,
00040     <a class="code" href="server_8c.html#a33a3">WATCH_FD_EXCP</a>   = 1 &lt;&lt; 3
00041 };
00042 
00043 <span class="keyword">static</span> <span class="keywordtype">void</span> server_watch_fd(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> fd, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> mode);
00044 <span class="keyword">static</span> <span class="keywordtype">void</span> server_clear_fd(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> fd, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> mode);
00045 <span class="keyword">static</span> <span class="keywordtype">void</span> server_close_fd(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> fd);
00046 
00047 <span class="keyword">static</span> <span class="keywordtype">int</span> server_be_listen(<a class="code" href="structbackend__s.html">backend_t</a> *be)
00048 {
00049     <span class="keyword">enum</span> { DEFAULT_BACKLOG = 1024 };
00050     <span class="keywordtype">int</span> d = 0, backlog = 0, val = 1;
00051     u_config_t *subkey;
00052 
00053     dbg_return_if (be == NULL, ~0);
00054     dbg_return_if (be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a> == NULL, ~0);
00055 
00056     <span class="keywordflow">switch</span>(be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a>-&gt;<a class="code" href="structaddr__s.html#o0">type</a>)
00057     {
00058         <span class="keywordflow">case</span> ADDR_IPV4:
00059             dbg_err_if((d = socket(AF_INET, SOCK_STREAM, 0)) &lt; 0);
00060             dbg_err_if(setsockopt(d, SOL_SOCKET, SO_REUSEADDR, (<span class="keywordtype">void</span> *)&amp;val, 
00061                 <span class="keyword">sizeof</span>(<span class="keywordtype">int</span>)) &lt; 0);
00062             dbg_err_if( bind(d, (<span class="keywordtype">void</span>*)&amp;be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a>-&gt;<a class="code" href="structaddr__s.html#o4">sa</a>.<a class="code" href="structaddr__s.html#o1">sin</a>, 
00063                 <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in)));
00064             <span class="keywordflow">break</span>;
00065         <span class="keywordflow">case</span> ADDR_IPV6:
00066         <span class="keywordflow">case</span> ADDR_UNIX:
00067         <span class="keywordflow">default</span>:
00068             dbg_err_if(<span class="stringliteral">"unupported addr type"</span>);
00069     }
00070 
00071     <span class="keywordflow">if</span>(!u_config_get_subkey(be-&gt;<a class="code" href="structbackend__s.html#o5">config</a>, <span class="stringliteral">"backlog"</span>, &amp;subkey))
00072         backlog = atoi(u_config_get_value(subkey));
00073 
00074     <span class="keywordflow">if</span>(!backlog)
00075         backlog = DEFAULT_BACKLOG;
00076 
00077     dbg_err_if(listen(d, backlog));
00078 
00079     be-&gt;<a class="code" href="structbackend__s.html#o8">ld</a> = d;
00080 
00081     <span class="keywordflow">return</span> 0;
00082 err:
00083     warn_strerror(errno);
00084     <span class="keywordflow">if</span>(d)
00085         close(d);
00086     <span class="keywordflow">return</span> ~0;
00087 }
00088 
00089 
00090 <span class="preprocessor">#ifdef OS_UNIX</span>
00091 <span class="preprocessor"></span><span class="comment">/* remove a child process whose pid is 'pid' to children list */</span>
00092 <span class="keyword">static</span> <span class="keywordtype">int</span> server_reap_child(<a class="code" href="structserver__s.html">server_t</a> *s, pid_t pid)
00093 {
00094     <a class="code" href="structchild__s.html">child_t</a> *child;
00095     <a class="code" href="structbackend__s.html">backend_t</a> *be;
00096 
00097     dbg_err_if (s == NULL);
00098     
00099     <span class="comment">/* get the child object */</span>
00100     dbg_err_if(<a class="code" href="child_8h.html#a14">children_get_by_pid</a>(s-&gt;<a class="code" href="structserver__s.html#o5">children</a>, pid, &amp;child));
00101 
00102     <span class="comment">/* remove the child from the list */</span>
00103     dbg_err_if(<a class="code" href="child_8h.html#a11">children_del</a>(s-&gt;<a class="code" href="structserver__s.html#o5">children</a>, child));
00104     be = child-&gt;<a class="code" href="structchild__s.html#o1">be</a>;
00105 
00106     <span class="comment">/* check that the minimum number of process are active */</span>
00107     be-&gt;<a class="code" href="structbackend__s.html#o12">nchild</a>--;
00108     <span class="keywordflow">if</span>(be-&gt;<a class="code" href="structbackend__s.html#o12">nchild</a> &lt; be-&gt;<a class="code" href="structbackend__s.html#o14">start_child</a>)
00109         be-&gt;<a class="code" href="structbackend__s.html#o16">fork_child</a> = be-&gt;<a class="code" href="structbackend__s.html#o14">start_child</a> - be-&gt;<a class="code" href="structbackend__s.html#o12">nchild</a>;
00110 
00111     U_FREE(child);
00112 
00113     <span class="keywordflow">return</span> 0;
00114 err:
00115     <span class="keywordflow">return</span> ~0;
00116 }
00117 
00118 <span class="comment">/* add a child to the list */</span>
00119 <span class="keyword">static</span> <span class="keywordtype">int</span> server_add_child(<a class="code" href="structserver__s.html">server_t</a> *s, pid_t pid, <a class="code" href="structbackend__s.html">backend_t</a> *be)
00120 {
00121     <a class="code" href="structchild__s.html">child_t</a> *child = NULL;
00122 
00123     dbg_err_if (s == NULL);
00124     dbg_err_if (be == NULL);
00125 
00126     dbg_err_if(<a class="code" href="child_8h.html#a2">child_create</a>(pid, be, &amp;child));
00127 
00128     dbg_err_if(<a class="code" href="child_8h.html#a12">children_add</a>(s-&gt;<a class="code" href="structserver__s.html#o5">children</a>, child));
00129 
00130     be-&gt;<a class="code" href="structbackend__s.html#o12">nchild</a>++;
00131 
00132     <span class="keywordflow">return</span> 0;
00133 err:
00134     <span class="keywordflow">return</span> ~0;
00135 }
00136 
00137 <span class="comment">/* send 'sig' signal to all children process */</span>
00138 <span class="keyword">static</span> <span class="keywordtype">int</span> server_signal_children(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> sig)
00139 {
00140     <a class="code" href="structchild__s.html">child_t</a> *child;
00141     ssize_t i;
00142 
00143     dbg_return_if (s == NULL, ~0);
00144     
00145     <span class="keywordflow">for</span>(i = <a class="code" href="child_8h.html#a10">children_count</a>(s-&gt;<a class="code" href="structserver__s.html#o5">children</a>) - 1; i &gt;= 0; --i)
00146     {
00147         <span class="keywordflow">if</span>(!<a class="code" href="child_8h.html#a13">children_getn</a>(s-&gt;<a class="code" href="structserver__s.html#o5">children</a>, i, &amp;child))
00148             dbg_err_if(kill(child-&gt;<a class="code" href="structchild__s.html#o0">pid</a>, sig) &lt; 0);
00149     }
00150 
00151     <span class="keywordflow">return</span> 0;
00152 err:
00153     dbg_strerror(errno);
00154     <span class="keywordflow">return</span> ~0;
00155 }
00156 <span class="preprocessor">#endif</span>
00157 <span class="preprocessor"></span>
00158 <span class="keyword">static</span> <span class="keywordtype">void</span> server_term_children(<a class="code" href="structserver__s.html">server_t</a> *s)
00159 {
00160     dbg_ifb(s == NULL) <span class="keywordflow">return</span>;
00161 <span class="preprocessor">#ifdef OS_UNIX</span>
00162 <span class="preprocessor"></span>    server_signal_children(s, SIGTERM);
00163 <span class="preprocessor">#endif</span>
00164 <span class="preprocessor"></span>    <span class="keywordflow">return</span>;
00165 }
00166 
00167 <span class="keyword">static</span> <span class="keywordtype">void</span> server_kill_children(<a class="code" href="structserver__s.html">server_t</a> *s)
00168 {
00169     dbg_ifb(s == NULL) <span class="keywordflow">return</span>;
00170 <span class="preprocessor">#ifdef OS_UNIX</span>
00171 <span class="preprocessor"></span>    server_signal_children(s, SIGKILL);
00172 <span class="preprocessor">#endif</span>
00173 <span class="preprocessor"></span>    <span class="keywordflow">return</span>;
00174 }
00175 
00176 <span class="keyword">static</span> <span class="keywordtype">void</span> server_sigint(<span class="keywordtype">int</span> sig)
00177 {
00178     u_unused_args(sig);
00179     dbg(<span class="stringliteral">"SIGINT"</span>);
00180     <span class="keywordflow">if</span>(<a class="code" href="entry_8c.html#a3">ctx</a> &amp;&amp; <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;server)
00181         <a class="code" href="server_8h.html#a15">server_stop</a>(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;server);
00182 }
00183 
00184 <span class="keyword">static</span> <span class="keywordtype">void</span> server_sigterm(<span class="keywordtype">int</span> sig)
00185 {
00186     u_unused_args(sig);
00187 
00188     <span class="comment">/* child process die immediately.</span>
00189 <span class="comment">     * note: don't call debug functions because the parent process could be</span>
00190 <span class="comment">     * already dead if the user used the "killall kloned" command */</span>
00191     <span class="keywordflow">if</span>(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;pipc)
00192         _exit(0); 
00193 
00194     dbg(<span class="stringliteral">"SIGTERM"</span>);
00195 
00196     <span class="keywordflow">if</span>(<a class="code" href="entry_8c.html#a3">ctx</a> &amp;&amp; <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;server)
00197         <a class="code" href="server_8h.html#a15">server_stop</a>(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;server);
00198 }
00199 
00200 <span class="preprocessor">#ifdef OS_UNIX</span>
00201 <span class="preprocessor"></span><span class="keyword">static</span> <span class="keywordtype">void</span> server_sigchld(<span class="keywordtype">int</span> sig)
00202 {
00203     <a class="code" href="structserver__s.html">server_t</a> *s = <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;server;
00204 
00205     u_unused_args(sig);
00206 
00207     s-&gt;<a class="code" href="structserver__s.html#o19">reap_children</a> = 1;
00208 }
00209 
00210 <span class="keyword">static</span> <span class="keywordtype">void</span> server_waitpid(<a class="code" href="structserver__s.html">server_t</a> *s)
00211 {
00212     pid_t pid = -1;
00213     <span class="keywordtype">int</span> status;
00214 
00215     dbg_ifb(s == NULL) <span class="keywordflow">return</span>;
00216     
00217     <a class="code" href="utils_8h.html#a39">u_sig_block</a>(SIGCHLD);
00218 
00219     <span class="comment">/* detach from child processes */</span>
00220     <span class="keywordflow">while</span>((pid = waitpid(-1, &amp;status, WNOHANG)) &gt; 0) 
00221     {
00222         <span class="keywordflow">if</span>(WIFEXITED(status) &amp;&amp; WEXITSTATUS(status) != EXIT_SUCCESS)
00223             warn(<span class="stringliteral">"pid [%u], exit code [%d]"</span>, pid, WEXITSTATUS(status));
00224 
00225         <span class="keywordflow">if</span>(WIFSIGNALED(status))
00226             warn(<span class="stringliteral">"pid [%u], signal [%d]"</span>, pid, WTERMSIG(status));
00227 
00228         <span class="comment">/* decrement child count */</span>
00229         server_reap_child(s, pid);
00230     }
00231 
00232     s-&gt;<a class="code" href="structserver__s.html#o19">reap_children</a> = 0;
00233 
00234     <a class="code" href="utils_8h.html#a40">u_sig_unblock</a>(SIGCHLD);
00235 }
00236 <span class="preprocessor">#endif</span>
00237 <span class="preprocessor"></span>
00238 <span class="keyword">static</span> <span class="keywordtype">void</span> server_recalc_hfd(<a class="code" href="structserver__s.html">server_t</a> *s)
00239 {
00240     <span class="keyword">register</span> <span class="keywordtype">int</span> i;
00241     fd_set *prdfds, *pwrfds, *pexfds;
00242 
00243     dbg_ifb(s == NULL) <span class="keywordflow">return</span>;
00244     
00245     prdfds = &amp;s-&gt;<a class="code" href="structserver__s.html#o6">rdfds</a>;
00246     pwrfds = &amp;s-&gt;<a class="code" href="structserver__s.html#o7">wrfds</a>;
00247     pexfds = &amp;s-&gt;<a class="code" href="structserver__s.html#o8">exfds</a>;
00248 
00249     <span class="comment">/* set s-&gt;hfd to highest value */</span>
00250     <span class="keywordflow">for</span>(i = s-&gt;<a class="code" href="structserver__s.html#o12">hfd</a>, s-&gt;<a class="code" href="structserver__s.html#o12">hfd</a> = 0; i &gt; 0; --i)
00251     {
00252         <span class="keywordflow">if</span>(FD_ISSET(i, prdfds) || FD_ISSET(i, pwrfds) || FD_ISSET(i, pexfds))
00253         {
00254             s-&gt;<a class="code" href="structserver__s.html#o12">hfd</a> = i;
00255             <span class="keywordflow">break</span>;
00256         }
00257     }
00258 }
00259 
00260 <span class="keyword">static</span> <span class="keywordtype">void</span> server_clear_fd(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> fd, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> mode)
00261 {
00262     dbg_ifb(s == NULL) <span class="keywordflow">return</span>;
00263 
00264     <span class="keywordflow">if</span>(mode &amp; WATCH_FD_READ)
00265         FD_CLR(fd, &amp;s-&gt;<a class="code" href="structserver__s.html#o6">rdfds</a>);
00266 
00267     <span class="keywordflow">if</span>(mode &amp; WATCH_FD_WRITE)
00268         FD_CLR(fd, &amp;s-&gt;<a class="code" href="structserver__s.html#o7">wrfds</a>);
00269 
00270     <span class="keywordflow">if</span>(mode &amp; WATCH_FD_EXCP)
00271         FD_CLR(fd, &amp;s-&gt;<a class="code" href="structserver__s.html#o8">exfds</a>);
00272 
00273     server_recalc_hfd(s);
00274 }
00275 
00276 <span class="keyword">static</span> <span class="keywordtype">void</span> server_watch_fd(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> fd, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> mode)
00277 {
00278     dbg_ifb(s == NULL) <span class="keywordflow">return</span>;
00279     dbg_ifb(fd &lt; 0) return;
00280 
00281     if(mode &amp; WATCH_FD_READ)
00282         FD_SET(fd, &amp;s-&gt;rdfds);
00283 
00284     if(mode &amp; WATCH_FD_WRITE)
00285         FD_SET(fd, &amp;s-&gt;wrfds);
00286 
00287     if(mode &amp; WATCH_FD_EXCP)
00288         FD_SET(fd, &amp;s-&gt;exfds);
00289 
00290     s-&gt;hfd = MAX(s-&gt;hfd, fd);
00291 }
00292 
00293 static <span class="keywordtype">void</span> server_close_fd(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> fd)
00294 {
00295     dbg_ifb(s == NULL) <span class="keywordflow">return</span>;
00296     dbg_ifb(fd &lt; 0) return;
00297 
00298     server_clear_fd(s, fd, WATCH_FD_READ | WATCH_FD_WRITE | WATCH_FD_EXCP);
00299     close(fd);
00300 }
00301 
00302 static <span class="keywordtype">int</span> server_be_accept(<a class="code" href="structserver__s.html">server_t</a> *s, <a class="code" href="structbackend__s.html">backend_t</a> *be, <span class="keywordtype">int</span> *pfd)
00303 {
00304     <span class="keyword">struct </span>sockaddr sa;
00305     <span class="keywordtype">int</span> sa_len = <span class="keyword">sizeof</span>(<span class="keyword">struct </span>sockaddr);
00306     <span class="keywordtype">int</span> ad;
00307 
00308     u_unused_args(s);
00309 
00310     dbg_return_if (be == NULL, ~0);
00311     dbg_return_if (pfd == NULL, ~0);
00312 
00313 again:
00314     ad = accept(be-&gt;ld, &amp;sa, &amp;sa_len);
00315     <span class="keywordflow">if</span>(ad == -1 &amp;&amp; errno == EINTR)
00316         <span class="keywordflow">goto</span> again; <span class="comment">/* interrupted */</span>
00317     dbg_err_if(ad == -1); <span class="comment">/* accept error */</span>
00318 
00319     *pfd = ad;
00320 
00321     <span class="keywordflow">return</span> 0;
00322 err:
00323     <span class="keywordflow">if</span>(ad &lt; 0)
00324         dbg_strerror(errno);
00325     <span class="keywordflow">return</span> ~0;
00326 }
00327 
00328 <span class="keyword">static</span> <span class="keywordtype">int</span> server_backend_detach(<a class="code" href="structserver__s.html">server_t</a> *s, <a class="code" href="structbackend__s.html">backend_t</a> *be)
00329 {
00330     s-&gt;<a class="code" href="structserver__s.html#o13">nbackend</a>--;
00331 
00332     dbg_return_if (s == NULL, ~0);
00333     dbg_return_if (be == NULL, ~0);
00334 
00335     <a class="code" href="addr_8h.html#a7">addr_free</a>(be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a>);
00336     be-&gt;<a class="code" href="structbackend__s.html#o4">server</a> = NULL;
00337     be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a> = NULL;
00338     be-&gt;<a class="code" href="structbackend__s.html#o5">config</a> = NULL;
00339 
00340     close(be-&gt;<a class="code" href="structbackend__s.html#o8">ld</a>);
00341     be-&gt;<a class="code" href="structbackend__s.html#o8">ld</a> = -1;
00342 
00343     <a class="code" href="backend_8h.html#a7">backend_free</a>(be);
00344 
00345     <span class="keywordflow">return</span> 0;
00346 }
00347 
00348 <span class="preprocessor">#ifdef OS_UNIX</span>
00349 <span class="preprocessor"></span><span class="keyword">static</span> <span class="keywordtype">int</span> server_chroot_to(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keyword">const</span> <span class="keywordtype">char</span> *dir)
00350 {
00351     dbg_return_if (s == NULL, ~0);
00352     dbg_return_if (dir == NULL, ~0);
00353 
00354     u_unused_args(s);
00355 
00356     dbg_err_if(chroot((<span class="keywordtype">char</span>*)dir));
00357 
00358     dbg_err_if(chdir(<span class="stringliteral">"/"</span>));
00359 
00360     dbg(<span class="stringliteral">"chroot'd: %s"</span>, dir);
00361 
00362     <span class="keywordflow">return</span> 0;
00363 err:
00364     dbg_strerror(errno);
00365     <span class="keywordflow">return</span> ~0;
00366 }
00367 
00368 <span class="keyword">static</span> <span class="keywordtype">int</span> server_foreach_cb(<span class="keyword">struct</span> dirent *d, <span class="keyword">const</span> <span class="keywordtype">char</span> *path, <span class="keywordtype">void</span> *arg)
00369 {
00370     <span class="keywordtype">int</span> *pfound = (<span class="keywordtype">int</span>*)arg;
00371 
00372     u_unused_args(d, path);
00373 
00374     *pfound = 1;
00375 
00376     <span class="keywordflow">return</span> ~0;
00377 }
00378 
00379 <span class="keyword">static</span> <span class="keywordtype">int</span> server_chroot_blind(<a class="code" href="structserver__s.html">server_t</a> *s)
00380 {
00381     <span class="keyword">enum</span> { BLIND_DIR_MODE = 0100 }; <span class="comment">/* blind dir mode must be 0100 */</span>
00382     <span class="keywordtype">char</span> dir[U_PATH_MAX];
00383     <span class="keyword">struct </span>stat st;
00384     <span class="keywordtype">int</span> fd_dir = -1, found;
00385     pid_t child;
00386     <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> mask;
00387 
00388     dbg_err_if (s == NULL);
00389     dbg_err_if (s-&gt;<a class="code" href="structserver__s.html#o9">chroot</a> == NULL);
00390 
00391     dbg_err_if(u_path_snprintf(dir, U_PATH_MAX, U_PATH_SEPARATOR,
00392         <span class="stringliteral">"%s/kloned_blind_chroot_%d.dir"</span>, s-&gt;<a class="code" href="structserver__s.html#o9">chroot</a>, getpid()));
00393 
00394     <span class="comment">/* create the blind dir (0100 mode) */</span>
00395     dbg_err_if(mkdir(dir, BLIND_DIR_MODE ));
00396 
00397     <span class="comment">/* get the fd of the dir */</span>
00398     dbg_err_if((fd_dir = open(dir, O_RDONLY, 0)) &lt; 0);
00399 
00400     dbg_err_if((child = fork()) &lt; 0);
00401 
00402     <span class="keywordflow">if</span>(child == 0)
00403     {   <span class="comment">/* child */</span>
00404 
00405         <span class="comment">/* delete the chroot dir and exit */</span>
00406         sleep(1); <span class="comment">// FIXME use a lock here</span>
00407         dbg(<span class="stringliteral">"[child] removing dir: %s\n"</span>, dir);
00408         rmdir(dir);
00409         _exit(0);
00410     }
00411     <span class="comment">/* parent */</span>
00412 
00413     <span class="comment">/* do chroot */</span>
00414     dbg_err_if(server_chroot_to(s, dir));
00415 
00416     <span class="comment">/* do some dir sanity checks */</span>
00417 
00418     <span class="comment">/* get stat values */</span>
00419     dbg_err_if(fstat(fd_dir, &amp;st));
00420 
00421     <span class="comment">/* the dir owned must be root */</span>
00422     dbg_err_if(st.st_gid || st.st_uid);
00423 
00424     <span class="comment">/* the dir mode must be 0100 */</span>
00425     dbg_err_if((st.st_mode &amp; 07777) != BLIND_DIR_MODE);
00426 
00427     <span class="comment">/* the dir must be empty */</span>
00428     found = 0;
00429     mask = S_IFIFO | S_IFCHR | S_IFDIR | S_IFBLK | S_IFREG | S_IFLNK | S_IFSOCK;
00430     dbg_err_if(<a class="code" href="group__u__t.html#ga11">u_foreach_dir_item</a>(<span class="stringliteral">"/"</span>, mask, server_foreach_cb, &amp;found));
00431 
00432     <span class="comment">/* bail out if the dir is not empty */</span>
00433     dbg_err_if(found);
00434 
00435     close(fd_dir);
00436 
00437     <span class="keywordflow">return</span> 0;
00438 err:
00439     <span class="keywordflow">if</span>(fd_dir &gt;= 0)
00440         close(fd_dir);
00441     dbg_strerror(errno);
00442     <span class="keywordflow">return</span> ~0;
00443 }
00444 
00445 <span class="keyword">static</span> <span class="keywordtype">int</span> server_chroot(<a class="code" href="structserver__s.html">server_t</a> *s)
00446 {
00447     dbg_return_if (s == NULL, ~0);
00448 
00449     <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o21">blind_chroot</a>)
00450         <span class="keywordflow">return</span> server_chroot_blind(s);
00451     <span class="keywordflow">else</span>
00452         <span class="keywordflow">return</span> server_chroot_to(s, s-&gt;<a class="code" href="structserver__s.html#o9">chroot</a>);
00453 }
00454 
00455 <span class="keyword">static</span> <span class="keywordtype">int</span> server_drop_privileges(<a class="code" href="structserver__s.html">server_t</a> *s)
00456 {
00457     uid_t uid;
00458     gid_t gid;
00459 
00460     dbg_return_if (s == NULL, ~0);
00461 
00462     <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o11">gid</a> &gt; 0)
00463     {
00464         gid = (gid_t)s-&gt;<a class="code" href="structserver__s.html#o11">gid</a>;;
00465 
00466         <span class="comment">/* remove all groups except gid */</span>
00467         dbg_err_if(setgroups(1, &amp;gid));
00468 
00469         <span class="comment">/* set gid */</span>
00470         dbg_err_if(setgid(gid));
00471         dbg_err_if(setegid(gid));
00472 
00473         <span class="comment">/* verify */</span>
00474         dbg_err_if(getgid() != gid || getegid() != gid);
00475     }
00476 
00477     <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o10">uid</a> &gt; 0)
00478     {
00479         uid = (uid_t)s-&gt;<a class="code" href="structserver__s.html#o10">uid</a>;
00480 
00481         <span class="comment">/* set uid */</span>
00482         dbg_err_if(setuid(uid));
00483         dbg_err_if(seteuid(uid));
00484 
00485         <span class="comment">/* verify */</span>
00486         dbg_err_if(getuid() != uid || geteuid() != uid);
00487     }
00488     
00489     <span class="keywordflow">return</span> 0;
00490 err:
00491     dbg_strerror(errno);
00492     <span class="keywordflow">return</span> ~0;
00493 }
00494 
00495 <span class="keyword">static</span> <span class="keywordtype">int</span> server_fork_child(<a class="code" href="structserver__s.html">server_t</a> *s, <a class="code" href="structbackend__s.html">backend_t</a> *be)
00496 {
00497     <a class="code" href="structbackend__s.html">backend_t</a> *obe; <span class="comment">/* other backed */</span>
00498     pid_t child;
00499     <span class="keywordtype">int</span> socks[2];
00500 
00501     dbg_return_if (s == NULL, -1);
00502     dbg_return_if (be == NULL, -1);
00503     <span class="comment">/* exit on too much children */</span>
00504     dbg_return_if (<a class="code" href="child_8h.html#a10">children_count</a>(s-&gt;<a class="code" href="structserver__s.html#o5">children</a>) == s-&gt;<a class="code" href="structserver__s.html#o15">max_child</a>, -1);
00505     dbg_return_if (be-&gt;<a class="code" href="structbackend__s.html#o12">nchild</a> == be-&gt;<a class="code" href="structbackend__s.html#o13">max_child</a>, -1);
00506 
00507     <span class="comment">/* create a parent&lt;-&gt;child IPC channel */</span>
00508     dbg_err_if(socketpair(AF_UNIX, SOCK_STREAM, 0, socks) &lt; 0);
00509 
00510     <span class="keywordflow">if</span>((child = fork()) == 0)
00511     {   <span class="comment">/* child */</span>
00512 
00513         <span class="comment">/* never flush, the parent process will */</span>
00514         s-&gt;<a class="code" href="structserver__s.html#o18">klog_flush</a> = 0;
00515 
00516         <span class="comment">/* reseed the PRNG */</span>
00517         srand(rand() + getpid() + time(0));
00518 
00519         <span class="comment">/* close one end of the channel */</span>
00520         close(socks[0]);
00521 
00522         <span class="comment">/* save parent PPC socket and close the other */</span>
00523         <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;pipc = socks[1];
00524         <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend = be;
00525 
00526         <span class="comment">/* close listening sockets of other backends */</span>
00527         LIST_FOREACH(obe, &amp;s-&gt;<a class="code" href="structserver__s.html#o2">bes</a>, np)
00528         {
00529             <span class="keywordflow">if</span>(obe == be)
00530                 <span class="keywordflow">continue</span>;
00531             close(obe-&gt;<a class="code" href="structbackend__s.html#o8">ld</a>);
00532             obe-&gt;<a class="code" href="structbackend__s.html#o8">ld</a> = -1;
00533         }
00534 
00535         <span class="comment">/* clear child copy of children list */</span>
00536         dbg_err_if(<a class="code" href="child_8h.html#a9">children_clear</a>(s-&gt;<a class="code" href="structserver__s.html#o5">children</a>));
00537 
00538     } <span class="keywordflow">else</span> <span class="keywordflow">if</span>(child &gt; 0) {
00539         <span class="comment">/* parent */</span>
00540 
00541         <span class="comment">/* save child pid and increment child count */</span>
00542         server_add_child(s, child, be);
00543 
00544         <span class="comment">/* close one end of the channel */</span>
00545         close(socks[1]);
00546 
00547         <span class="comment">/* watch the PPC socket connected to the child */</span>
00548         server_watch_fd(s, socks[0], WATCH_FD_READ);
00549     } <span class="keywordflow">else</span> {
00550         warn_err(<span class="stringliteral">"fork error"</span>);
00551     }
00552 
00553     <span class="keywordflow">return</span> child;
00554 err:
00555     warn_strerror(errno);
00556     <span class="keywordflow">return</span> -1;
00557 }
00558 
00559 <span class="keyword">static</span> <span class="keywordtype">int</span> server_child_serve(<a class="code" href="structserver__s.html">server_t</a> *s, <a class="code" href="structbackend__s.html">backend_t</a> *be, <span class="keywordtype">int</span> ad)
00560 {
00561     pid_t child;
00562 
00563     dbg_return_if (s == NULL, ~0);
00564     dbg_return_if (be == NULL, ~0);
00565 
00566     dbg_err_if((child = server_fork_child(s, be)) &lt; 0);
00567 
00568     <span class="keywordflow">if</span>(child == 0)
00569     {   <span class="comment">/* child */</span>
00570 
00571         <span class="comment">/* close this be listening descriptor */</span>
00572         close(be-&gt;<a class="code" href="structbackend__s.html#o8">ld</a>);
00573 
00574         <span class="comment">/* serve the page */</span>
00575         dbg_if(<a class="code" href="backend_8h.html#a6">backend_serve</a>(be, ad));
00576 
00577         <span class="comment">/* close client socket and die */</span>
00578         close(ad);
00579         <a class="code" href="server_8h.html#a15">server_stop</a>(be-&gt;<a class="code" href="structbackend__s.html#o4">server</a>); 
00580     }
00581     <span class="comment">/* parent */</span>
00582 
00583     <span class="keywordflow">return</span> 0;
00584 err:
00585     warn_strerror(errno);
00586     <span class="keywordflow">return</span> ~0;
00587 }
00588 
00589 <span class="keyword">static</span> <span class="keywordtype">int</span> server_cb_spawn_child(<a class="code" href="timer_8h.html#a1">talarm_t</a> *al, <span class="keywordtype">void</span> *arg)
00590 {
00591     <a class="code" href="structserver__s.html">server_t</a> *s = (<a class="code" href="structserver__s.html">server_t</a>*)arg;
00592 
00593     u_unused_args(al);
00594 
00595     dbg_err_if (s == NULL);
00596 
00597     <span class="comment">/* must be called by a child process */</span>
00598     dbg_err_if(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend == NULL || <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;pipc == NULL);
00599 
00600     <span class="comment">/* ask the parent to create a new worker child process */</span>
00601     dbg_err_if(<a class="code" href="server__ppc__cmd_8h.html#a5">server_ppc_cmd_fork_child</a>(s, <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend));
00602 
00603     <span class="comment">/* mark the current child process so it will die when finishes </span>
00604 <span class="comment">       serving this page */</span>
00605     <a class="code" href="server_8h.html#a15">server_stop</a>(s);
00606 
00607     <span class="keywordflow">return</span> 0;
00608 err:
00609     <span class="keywordflow">return</span> ~0;
00610 }
00611 <span class="preprocessor">#endif </span><span class="comment">/* ifdef OS_UNIX */</span>
00612 
00613 <span class="keyword">static</span> <span class="keywordtype">int</span> server_be_serve(<a class="code" href="structserver__s.html">server_t</a> *s, <a class="code" href="structbackend__s.html">backend_t</a> *be, <span class="keywordtype">int</span> ad)
00614 {
00615     <a class="code" href="timer_8h.html#a1">talarm_t</a> *al = NULL;
00616 
00617     dbg_err_if (s == NULL);
00618     dbg_err_if (be == NULL);
00619     
00620     <span class="keywordflow">switch</span>(be-&gt;<a class="code" href="structbackend__s.html#o7">model</a>)
00621     {
00622 <span class="preprocessor">#ifdef OS_UNIX</span>
00623 <span class="preprocessor"></span>    <span class="keywordflow">case</span> <a class="code" href="server_8h.html#a20a7">SERVER_MODEL_FORK</a>:
00624         <span class="comment">/* spawn a child to handle the request */</span>
00625         dbg_err_if(server_child_serve(s, be, ad));
00626         <span class="keywordflow">break</span>;
00627 
00628     <span class="keywordflow">case</span> <a class="code" href="server_8h.html#a20a9">SERVER_MODEL_PREFORK</a>: 
00629         <span class="comment">/* FIXME lower timeout value may be needed */</span>
00630         <span class="comment">/* if _serve takes more then 1 second spawn a new worker process */</span>
00631         dbg_err_if(<a class="code" href="timer_8h.html#a3">timerm_add</a>(1, server_cb_spawn_child, (<span class="keywordtype">void</span>*)s, &amp;al));
00632 
00633         <span class="comment">/* serve the page */</span>
00634         dbg_if(<a class="code" href="backend_8h.html#a6">backend_serve</a>(be, ad));
00635 
00636         <span class="comment">/* remove and free the alarm */</span>
00637         <a class="code" href="timer_8h.html#a4">timerm_del</a>(al); <span class="comment">/* prefork */</span>
00638         <span class="keywordflow">break</span>;
00639 <span class="preprocessor">#endif</span>
00640 <span class="preprocessor"></span>
00641     <span class="keywordflow">case</span> <a class="code" href="server_8h.html#a20a8">SERVER_MODEL_ITERATIVE</a>:
00642         <span class="comment">/* serve the page */</span>
00643         dbg_if(<a class="code" href="backend_8h.html#a6">backend_serve</a>(be, ad));
00644         <span class="keywordflow">break</span>;
00645 
00646     <span class="keywordflow">default</span>:
00647         warn_err_if(<span class="stringliteral">"server model not supported"</span>);
00648     }
00649 
00650     <span class="comment">/* close the accepted (already served) socket */</span>
00651     close(ad);
00652 
00653     <span class="keywordflow">return</span> 0;
00654 err:
00655     close(ad);
00656     <span class="keywordflow">return</span> ~0;
00657 }
00658 
<a name="l00659"></a><a class="code" href="server_8h.html#a15">00659</a> <span class="keywordtype">int</span> <a class="code" href="server_8h.html#a15">server_stop</a>(<a class="code" href="structserver__s.html">server_t</a> *s)
00660 {
00661     dbg_err_if (s == NULL);
00662     
00663     <span class="keywordflow">if</span>(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;pipc)
00664     {   <span class="comment">/* child process */</span>
00665 
00666         dbg_err_if(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend == NULL);
00667 
00668         <span class="comment">/* close child listening sockets to force accept(2) to exit */</span>
00669         close(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend-&gt;ld);
00670     }
00671 
00672     <span class="comment">/* stop the parent process */</span>
00673     s-&gt;<a class="code" href="structserver__s.html#o16">stop</a> = 1;
00674 
00675     <span class="keywordflow">return</span> 0;
00676 err:
00677     <span class="keywordflow">return</span> ~0;
00678 }
00679 
00680 <span class="keyword">static</span> <span class="keywordtype">int</span> server_listen(<a class="code" href="structserver__s.html">server_t</a> *s)
00681 {
00682     <a class="code" href="structbackend__s.html">backend_t</a> *be;
00683 
00684     dbg_err_if (s == NULL);
00685     
00686     LIST_FOREACH(be, &amp;s-&gt;<a class="code" href="structserver__s.html#o2">bes</a>, np)
00687     {
00688         <span class="comment">/* bind to be-&gt;addr */</span>
00689         dbg_err_if(server_be_listen(be));
00690 
00691         <span class="comment">/* watch the listening socket */</span>
00692         <span class="keywordflow">if</span>(be-&gt;<a class="code" href="structbackend__s.html#o7">model</a> != SERVER_MODEL_PREFORK)
00693             server_watch_fd(s, be-&gt;<a class="code" href="structbackend__s.html#o8">ld</a>, WATCH_FD_READ);
00694     }
00695 
00696     <span class="keywordflow">return</span> 0;
00697 err:
00698     <span class="keywordflow">return</span> ~0;
00699 }
00700 
<a name="l00701"></a><a class="code" href="server_8h.html#a14">00701</a> <span class="keywordtype">int</span> <a class="code" href="server_8h.html#a14">server_cgi</a>(<a class="code" href="structserver__s.html">server_t</a> *s)
00702 {
00703     <a class="code" href="structbackend__s.html">backend_t</a> *be;
00704 
00705     dbg_err_if (s == NULL);
00706 
00707     <span class="comment">/* use the first http backend as the CGI backend */</span>
00708     LIST_FOREACH(be, &amp;s-&gt;<a class="code" href="structserver__s.html#o2">bes</a>, np)
00709     {
00710         <span class="keywordflow">if</span>(strcasecmp(be-&gt;<a class="code" href="structbackend__s.html#o0">proto</a>, <span class="stringliteral">"http"</span>) == 0)
00711         {
00712             dbg_if(<a class="code" href="backend_8h.html#a6">backend_serve</a>(be, 0));
00713             <span class="keywordflow">return</span> 0;
00714         }
00715     }
00716 
00717 err: <span class="comment">/* fall through if search loop exhausted */</span>
00718     <span class="keywordflow">return</span> ~0;
00719 }
00720 
<a name="l00721"></a><a class="code" href="server_8h.html#a16">00721</a> <a class="code" href="ppc_8h.html#a0">ppc_t</a>* <a class="code" href="server_8h.html#a16">server_get_ppc</a>(<a class="code" href="structserver__s.html">server_t</a> *s)
00722 {
00723     dbg_return_if (s == NULL, NULL);
00724 
00725     <span class="keywordflow">return</span> s-&gt;<a class="code" href="structserver__s.html#o1">ppc</a>;
00726 }
00727 
00728 <span class="keyword">static</span> <span class="keywordtype">int</span> server_process_ppc(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> fd)
00729 {
00730     <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> cmd;
00731     <span class="keywordtype">char</span> data[PPC_MAX_DATA_SIZE];
00732     ssize_t n;
00733 
00734     dbg_err_if (s == NULL);
00735     dbg_err_if (fd &lt; 0);
00736 
00737     <span class="comment">/* get a ppc request */</span>
00738     n = <a class="code" href="ppc_8h.html#a8">ppc_read</a>(s-&gt;<a class="code" href="structserver__s.html#o1">ppc</a>, fd, &amp;cmd, data, PPC_MAX_DATA_SIZE); 
00739     <span class="keywordflow">if</span>(n &gt; 0)
00740     {   
00741         <span class="comment">/* process a ppc (parent procedure call) request */</span>
00742         dbg_err_if(<a class="code" href="ppc_8h.html#a6">ppc_dispatch</a>(s-&gt;<a class="code" href="structserver__s.html#o1">ppc</a>, fd, cmd, data, n));
00743     } <span class="keywordflow">else</span> <span class="keywordflow">if</span>(n == 0) {
00744         <span class="comment">/* child has exit or closed the channel. close our side of the sock </span>
00745 <span class="comment">           and remove it from the watch list */</span>
00746         server_close_fd(s, fd);
00747     } <span class="keywordflow">else</span> {
00748         <span class="comment">/* ppc error. close fd and remove it from the watch list */</span>
00749         server_close_fd(s, fd);
00750     }
00751 
00752     <span class="keywordflow">return</span> 0;
00753 err:
00754     <span class="keywordflow">return</span> ~0;
00755 }
00756 
00757 <span class="keyword">static</span> <span class="keywordtype">int</span> server_set_socket_opts(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> sock)
00758 {
00759     <span class="keywordtype">int</span> on = 1; 
00760 
00761     u_unused_args(s);
00762 
00763     dbg_err_if (sock &lt; 0);
00764 
00765     <span class="comment">/* disable Nagle algorithm */</span>
00766     dbg_err_if(setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, 
00767         (<span class="keywordtype">void</span>*) &amp;on, <span class="keyword">sizeof</span>(<span class="keywordtype">int</span>)) &lt; 0);
00768 
00769     <span class="keywordflow">return</span> 0;
00770 err:
00771     <span class="keywordflow">return</span> ~0;
00772 }
00773 
00774 <span class="keyword">static</span> <span class="keywordtype">int</span> server_dispatch(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> fd)
00775 {
00776     <a class="code" href="structbackend__s.html">backend_t</a> *be;
00777     <span class="keywordtype">int</span> ad = -1; 
00778 
00779     dbg_err_if (s == NULL);
00780 
00781     <span class="comment">/* find the backend that listen on fd */</span>
00782     LIST_FOREACH(be, &amp;s-&gt;<a class="code" href="structserver__s.html#o2">bes</a>, np)
00783         if(be-&gt;ld == fd)
00784             break;
00785 
00786     if(be == NULL) <span class="comment">/* a child is ppc-calling */</span>
00787         return server_process_ppc(s, fd);
00788 
00789     <span class="comment">/* accept the pending connection */</span>
00790     dbg_err_if(server_be_accept(s, be, &amp;ad));
00791 
00792     <span class="comment">/* set socket options on accepted socket */</span>
00793     dbg_err_if(server_set_socket_opts(s, ad));
00794 
00795     <span class="comment">/* serve the page */</span>
00796     dbg_err_if(server_be_serve(s, be, ad));
00797 
00798     return 0;
00799 err:
00800     U_CLOSE(ad);
00801     return ~0;
00802 }
00803 
<a name="l00804"></a><a class="code" href="server_8c.html#a23">00804</a> <span class="keywordtype">int</span> server_cb_klog_flush(<a class="code" href="timer_8h.html#a1">talarm_t</a> *a, <span class="keywordtype">void</span> *arg)
00805 {
00806     <a class="code" href="structserver__s.html">server_t</a> *s = (<a class="code" href="structserver__s.html">server_t</a>*)arg;
00807 
00808     u_unused_args(a);
00809 
00810     dbg_return_if (s == NULL, ~0);
00811 
00812     <span class="comment">/* set a flag to flush the klog object in server_loop */</span>
00813     s-&gt;<a class="code" href="structserver__s.html#o18">klog_flush</a>++;
00814 
00815     <span class="keywordflow">return</span> 0;
00816 }
00817 
00818 <span class="preprocessor">#ifdef OS_UNIX</span>
00819 <span class="preprocessor"></span><span class="keywordtype">int</span> <a class="code" href="server__s_8h.html#a2">server_spawn_child</a>(<a class="code" href="structserver__s.html">server_t</a> *s, <a class="code" href="structbackend__s.html">backend_t</a> *be)
00820 {
00821     size_t c;
00822     <span class="keywordtype">int</span> rc;
00823 
00824     dbg_err_if (s == NULL);
00825     dbg_err_if (be == NULL);
00826 
00827     dbg_err_if((rc = server_fork_child(s, be)) &lt; 0);
00828     <span class="keywordflow">if</span>(rc &gt; 0)
00829         <span class="keywordflow">return</span> 0; <span class="comment">/* parent */</span>
00830 
00831     <span class="comment">/* child main loop: </span>
00832 <span class="comment">       close on s-&gt;stop or if max # of request limit has reached (the </span>
00833 <span class="comment">       server will respawn a new process if needed) */</span>
00834     <span class="keywordflow">for</span>(c = 0; !s-&gt;<a class="code" href="structserver__s.html#o16">stop</a> &amp;&amp; c &lt; be-&gt;<a class="code" href="structbackend__s.html#o15">max_rq_xchild</a>; ++c)
00835     {
00836         <span class="comment">/* wait for a new client (will block on accept(2)) */</span>
00837         dbg_err_if(server_dispatch(s, be-&gt;<a class="code" href="structbackend__s.html#o8">ld</a>));
00838     }
00839 
00840     <a class="code" href="server_8h.html#a15">server_stop</a>(s);
00841 
00842     <span class="keywordflow">return</span> 0;
00843 err:
00844     <span class="keywordflow">return</span> ~0;
00845 }
00846 
00847 <span class="comment">/* spawn pre-fork child processes */</span>
00848 <span class="keyword">static</span> <span class="keywordtype">int</span> server_spawn_children(<a class="code" href="structserver__s.html">server_t</a> *s)
00849 {
00850     <a class="code" href="structbackend__s.html">backend_t</a> *be;
00851     <span class="keyword">register</span> size_t i;
00852 
00853     dbg_err_if (s == NULL);
00854 
00855     <span class="comment">/* spawn N child process that will sleep asap into accept(2) */</span>
00856     LIST_FOREACH (be, &amp;s-&gt;<a class="code" href="structserver__s.html#o2">bes</a>, np)
00857     {
00858         <span class="keywordflow">if</span>(be-&gt;<a class="code" href="structbackend__s.html#o7">model</a> != <a class="code" href="server_8h.html#a20a9">SERVER_MODEL_PREFORK</a> || be-&gt;<a class="code" href="structbackend__s.html#o16">fork_child</a> == 0)
00859             <span class="keywordflow">continue</span>;
00860 
00861         <span class="comment">/* spawn be-&gt;fork_child child processes */</span>
00862         <span class="keywordflow">for</span>(i = 0; i &lt; be-&gt;<a class="code" href="structbackend__s.html#o16">fork_child</a>; ++i)
00863         {
00864             dbg_err_if(<a class="code" href="server__s_8h.html#a2">server_spawn_child</a>(s, be));
00865             be-&gt;<a class="code" href="structbackend__s.html#o16">fork_child</a>--;
00866         }
00867     }
00868 
00869     <span class="keywordflow">return</span> 0;
00870 err:
00871     <span class="keywordflow">return</span> ~0;
00872 }
00873 <span class="preprocessor">#endif</span>
00874 <span class="preprocessor"></span>
<a name="l00875"></a><a class="code" href="server_8h.html#a13">00875</a> <span class="keywordtype">int</span> <a class="code" href="server_8h.html#a13">server_loop</a>(<a class="code" href="structserver__s.html">server_t</a> *s)
00876 {
00877     <span class="keyword">struct </span>timeval tv;
00878     <span class="keywordtype">int</span> rc, fd;
00879     fd_set rdfds, wrfds, exfds;
00880 
00881     dbg_err_if (s == NULL);
00882     dbg_err_if (s-&gt;<a class="code" href="structserver__s.html#o0">config</a> == NULL);
00883 
00884     dbg_err_if(server_listen(s));
00885 
00886 <span class="preprocessor">#ifdef OS_UNIX</span>
00887 <span class="preprocessor"></span>    <span class="comment">/* if it's configured chroot to the dst dir */</span>
00888     <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o9">chroot</a>)
00889         dbg_err_if(server_chroot(s));
00890 
00891     <span class="comment">/* set uid/gid to non-root user */</span>
00892     dbg_err_if(server_drop_privileges(s));
00893 
00894     <span class="comment">/* if allow_root is not set check that we're not running as root */</span>
00895     <span class="keywordflow">if</span>(!s-&gt;<a class="code" href="structserver__s.html#o20">allow_root</a>)
00896         warn_err_ifm(!getuid() || !geteuid() || !getgid() || !getegid(),
00897             <span class="stringliteral">"you must set the allow_root config option to run kloned as root"</span>);
00898 <span class="preprocessor">#endif</span>
00899 <span class="preprocessor"></span>
00900     <span class="keywordflow">for</span>(; !s-&gt;<a class="code" href="structserver__s.html#o16">stop</a>; )
00901     {
00902 <span class="preprocessor">#ifdef OS_UNIX</span>
00903 <span class="preprocessor"></span>        <span class="comment">/* spawn new child if needed (may fail on resource limits) */</span>
00904         dbg_if(server_spawn_children(s));
00905 <span class="preprocessor">#endif</span>
00906 <span class="preprocessor"></span>
00907         <span class="comment">/* children in pre-fork mode exit here */</span>
00908         <span class="keywordflow">if</span>(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;pipc)
00909             <span class="keywordflow">break</span>;
00910 
00911         memcpy(&amp;rdfds, &amp;s-&gt;<a class="code" href="structserver__s.html#o6">rdfds</a>, <span class="keyword">sizeof</span>(fd_set));
00912         memcpy(&amp;wrfds, &amp;s-&gt;<a class="code" href="structserver__s.html#o7">wrfds</a>, <span class="keyword">sizeof</span>(fd_set));
00913         memcpy(&amp;exfds, &amp;s-&gt;<a class="code" href="structserver__s.html#o8">exfds</a>, <span class="keyword">sizeof</span>(fd_set));
00914 
00915         <span class="comment">/* wake up every second */</span>
00916         tv.tv_sec = 1; tv.tv_usec = 0;
00917 
00918     again:
00919         rc = select(1 + s-&gt;<a class="code" href="structserver__s.html#o12">hfd</a>, &amp;rdfds, &amp;wrfds, &amp;exfds, &amp;tv); 
00920         <span class="keywordflow">if</span>(rc == -1 &amp;&amp; errno == EINTR)
00921             <span class="keywordflow">goto</span> again; <span class="comment">/* interrupted */</span>
00922         dbg_err_if(rc == -1); <span class="comment">/* select error */</span>
00923 
00924 <span class="preprocessor">#ifdef OS_UNIX</span>
00925 <span class="preprocessor"></span>        <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o19">reap_children</a>)
00926             server_waitpid(s);
00927 <span class="preprocessor">#endif</span>
00928 <span class="preprocessor"></span>
00929         <span class="comment">/* call klog_flush if flush timeout has expired and select() timeouts */</span>
00930         <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o18">klog_flush</a> &amp;&amp; <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;pipc == NULL)
00931         {
00932             <span class="comment">/* flush the log buffer */</span>
00933             <a class="code" href="klog_8h.html#a27">klog_flush</a>(s-&gt;<a class="code" href="structserver__s.html#o3">klog</a>);
00934 
00935             <span class="comment">/* reset the flag */</span>
00936             s-&gt;<a class="code" href="structserver__s.html#o18">klog_flush</a> = 0; 
00937 
00938             U_FREE(s-&gt;<a class="code" href="structserver__s.html#o4">al_klog_flush</a>);
00939 
00940             <span class="comment">/* re-set the timer */</span>
00941             dbg_err_if(<a class="code" href="timer_8h.html#a3">timerm_add</a>(<a class="code" href="server_8h.html#a19a1">SERVER_LOG_FLUSH_TIMEOUT</a>, 
00942                 <a class="code" href="server_8c.html#a23">server_cb_klog_flush</a>, s, &amp;s-&gt;<a class="code" href="structserver__s.html#o4">al_klog_flush</a>));
00943         }
00944 
00945         <span class="comment">/* for each signaled listening descriptor */</span>
00946         <span class="keywordflow">for</span>(fd = 0; rc &amp;&amp; fd &lt; 1 + s-&gt;<a class="code" href="structserver__s.html#o12">hfd</a>; ++fd)
00947         { 
00948             <span class="keywordflow">if</span>(FD_ISSET(fd, &amp;rdfds))
00949             {
00950                 --rc;
00951                 <span class="comment">/* dispatch the request to the right backend */</span>
00952                 dbg_if(server_dispatch(s, fd));
00953             } 
00954         } <span class="comment">/* for each ready fd */</span>
00955 
00956     } <span class="comment">/* !s-&gt;stop*/</span>
00957 
00958     <span class="comment">/* children in fork mode exit here */</span>
00959     <span class="keywordflow">if</span>(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;pipc)
00960         <span class="keywordflow">return</span> 0;
00961 
00962     <span class="comment">/* shutdown all children */</span>
00963     server_term_children(s);
00964 
00965     sleep(1);
00966 
00967     <span class="comment">/* brute kill children process */</span>
00968     <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o14">nchild</a>)
00969         server_kill_children(s);
00970 
00971     <span class="keywordflow">return</span> 0;
00972 err:
00973     <span class="keywordflow">return</span> ~0;
00974 }
00975 
<a name="l00976"></a><a class="code" href="server_8h.html#a12">00976</a> <span class="keywordtype">int</span> <a class="code" href="server_8h.html#a12">server_free</a>(<a class="code" href="structserver__s.html">server_t</a> *s)
00977 {
00978     <a class="code" href="structbackend__s.html">backend_t</a> *be;
00979 
00980     dbg_err_if (s == NULL);
00981 
00982     <span class="comment">/* remove the hook (that needs the server_t object) */</span>
00983     u_log_set_hook(NULL, NULL, NULL, NULL);
00984 
00985     <span class="comment">/* remove klog flushing alarm */</span>
00986     <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o4">al_klog_flush</a>)
00987     {
00988         <a class="code" href="timer_8h.html#a4">timerm_del</a>(s-&gt;<a class="code" href="structserver__s.html#o4">al_klog_flush</a>);
00989         s-&gt;<a class="code" href="structserver__s.html#o4">al_klog_flush</a> = NULL;
00990     }
00991 
00992     <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o3">klog</a>)
00993     {
00994         <span class="comment">/* child processes must not close klog when in 'file' mode, because </span>
00995 <span class="comment">           klog_file_t will flush data that the parent already flushed </span>
00996 <span class="comment">           (children inherit a "used" FILE* that will usually contain, on close,</span>
00997 <span class="comment">           not-empty buffer that fclose (called by exit()) flushes). same </span>
00998 <span class="comment">           thing may happens with different log devices when buffers are used.</span>
00999 <span class="comment">         */</span>
01000         <span class="keywordflow">if</span>(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;pipc == NULL)
01001             <a class="code" href="klog_8h.html#a26">klog_close</a>(s-&gt;<a class="code" href="structserver__s.html#o3">klog</a>);
01002         s-&gt;<a class="code" href="structserver__s.html#o3">klog</a> = NULL;
01003     }
01004 
01005     <span class="keywordflow">while</span>((be = LIST_FIRST(&amp;s-&gt;<a class="code" href="structserver__s.html#o2">bes</a>)) != NULL)
01006     {
01007         LIST_REMOVE(be, np);
01008         server_backend_detach(s, be);
01009     }
01010 
01011     dbg_if(<a class="code" href="ppc_8h.html#a4">ppc_free</a>(s-&gt;<a class="code" href="structserver__s.html#o1">ppc</a>));
01012 
01013     dbg_if(<a class="code" href="child_8h.html#a8">children_free</a>(s-&gt;<a class="code" href="structserver__s.html#o5">children</a>));
01014 
01015 <span class="preprocessor">#ifdef OS_WIN</span>
01016 <span class="preprocessor"></span>    WSACleanup();
01017 <span class="preprocessor">#endif</span>
01018 <span class="preprocessor"></span>
01019     U_FREE(s);
01020     <span class="keywordflow">return</span> 0;
01021 err:
01022     <span class="keywordflow">return</span> ~0;
01023 }
01024 
01025 <span class="keyword">static</span> <span class="keywordtype">int</span> server_setup_backend(<a class="code" href="structserver__s.html">server_t</a> *s, <a class="code" href="structbackend__s.html">backend_t</a> *be)
01026 {
01027     u_config_t *subkey;
01028 
01029     dbg_return_if (s == NULL, ~0);
01030     dbg_return_if (be == NULL, ~0);
01031     
01032     <span class="comment">/* server count */</span>
01033     s-&gt;<a class="code" href="structserver__s.html#o13">nbackend</a>++;
01034 
01035     <span class="comment">/* parse and create the bind addr_t */</span>
01036     warn_err_ifm(u_config_get_subkey(be-&gt;<a class="code" href="structbackend__s.html#o5">config</a>, <span class="stringliteral">"addr"</span>, &amp;subkey),
01037         <span class="stringliteral">"missing or bad '&lt;servname&gt;.addr' value"</span>);
01038 
01039     dbg_err_if(<a class="code" href="addr_8h.html#a1">addr_create</a>(&amp;be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a>));
01040 
01041     <span class="keywordflow">if</span>(strcasecmp(be-&gt;<a class="code" href="structbackend__s.html#o0">proto</a>, <span class="stringliteral">"https"</span>) == 0)
01042         dbg_err_if(<a class="code" href="addr_8h.html#a6">addr_set_ipv4_port</a>(be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a>, 443)); <span class="comment">/* default https port */</span>
01043     <span class="keywordflow">else</span>
01044         dbg_err_if(<a class="code" href="addr_8h.html#a6">addr_set_ipv4_port</a>(be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a>, 80)); <span class="comment">/* default http port */</span>
01045 
01046     dbg_err_if(<a class="code" href="addr_8h.html#a2">addr_set_from_config</a>(be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a>, subkey));
01047 
01048     <span class="keywordflow">return</span> 0;
01049 err:
01050     <span class="keywordflow">if</span>(be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a>)
01051     {
01052         <a class="code" href="addr_8h.html#a7">addr_free</a>(be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a>);
01053         be-&gt;<a class="code" href="structbackend__s.html#o6">addr</a> = NULL;
01054     }
01055     <span class="keywordflow">return</span> ~0;
01056 }
01057 
01058 <span class="keyword">static</span> <span class="keywordtype">int</span> server_log_hook(<span class="keywordtype">void</span> *arg, <span class="keywordtype">int</span> level, <span class="keyword">const</span> <span class="keywordtype">char</span> *str)
01059 {
01060     <a class="code" href="structserver__s.html">server_t</a> *s = (<a class="code" href="structserver__s.html">server_t</a>*)arg;
01061     u_log_hook_t old = NULL;
01062     <span class="keywordtype">void</span> *old_arg = NULL;
01063 
01064     dbg_err_if (s == NULL);
01065     dbg_err_if (str == NULL);
01066  
01067     <span class="comment">/* if both the server and the calling backend have no log then exit */</span>
01068     <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o3">klog</a> == NULL &amp;&amp; (<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend == NULL || <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend-&gt;klog == NULL))
01069         <span class="keywordflow">return</span> 0; <span class="comment">/* log is disabled */</span>
01070 
01071     <span class="comment">/* disable log hooking in the hook itself otherwise an infinite loop </span>
01072 <span class="comment">       may happen if a log function is called from inside the hook */</span>
01073     u_log_set_hook(NULL, NULL, &amp;old, &amp;old_arg);
01074 
01075     <span class="comment">/* syslog klog doesn't go through ppc */</span>
01076     <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o3">klog</a>-&gt;<a class="code" href="structklog__s.html#o0">type</a> == KLOG_TYPE_SYSLOG || <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;pipc == NULL)
01077     {   <span class="comment">/* syslog klog or parent context */</span>
01078         <span class="keywordflow">if</span>(s-&gt;<a class="code" href="structserver__s.html#o3">klog</a>)
01079             dbg_err_if(<a class="code" href="klog_8h.html#a25">klog</a>(s-&gt;<a class="code" href="structserver__s.html#o3">klog</a>, <a class="code" href="ppc__log__add_8c.html#a1">syslog_to_klog</a>(level), <span class="stringliteral">"%s"</span>, str));
01080     } <span class="keywordflow">else</span> {
01081         <span class="comment">/* children context */</span>
01082         dbg_err_if(<a class="code" href="server__ppc__cmd_8h.html#a3">server_ppc_cmd_log_add</a>(s, level, str));
01083     }
01084 
01085     <span class="comment">/* re-set the old hook */</span>
01086     u_log_set_hook(old, old_arg, NULL, NULL);
01087 
01088     <span class="keywordflow">return</span> 0;
01089 err:
01090     <span class="keywordflow">if</span>(old)
01091         u_log_set_hook(old, old_arg, NULL, NULL);
01092     <span class="keywordflow">return</span> ~0;
01093 }
01094 
<a name="l01095"></a><a class="code" href="server_8h.html#a17">01095</a> <span class="keywordtype">int</span> <a class="code" href="server_8h.html#a17">server_get_logger</a>(<a class="code" href="structserver__s.html">server_t</a> *s, <a class="code" href="structklog__s.html">klog_t</a> **pkl)
01096 {
01097     <a class="code" href="structklog__s.html">klog_t</a> *kl = NULL;
01098 
01099     dbg_err_if (s == NULL);
01100     dbg_err_if (pkl == NULL);
01101  
01102     <span class="keywordflow">if</span>(<a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend)
01103         kl = <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend-&gt;klog; <span class="comment">/* may be NULL */</span>
01104 
01105     <span class="keywordflow">if</span>(kl == NULL)
01106         kl = s-&gt;<a class="code" href="structserver__s.html#o3">klog</a>; <span class="comment">/* may be NULL */</span>
01107 
01108     *pkl = kl;
01109 
01110     <span class="keywordflow">return</span> 0;
01111 err:
01112     <span class="keywordflow">return</span> ~0;
01113 }
01114 
01115 <span class="keyword">static</span> <span class="keywordtype">int</span> server_get_klog_line(<a class="code" href="structserver__s.html">server_t</a> *s, <a class="code" href="structklog__s.html">klog_t</a> *kl, size_t i, <span class="keywordtype">char</span> *line)
01116 {
01117     <a class="code" href="structbackend__s.html">backend_t</a> *be = <a class="code" href="entry_8c.html#a3">ctx</a>-&gt;backend;
01118 
01119     dbg_err_if(kl-&gt;<a class="code" href="structklog__s.html#o0">type</a> != KLOG_TYPE_MEM);
01120     dbg_err_if(be == NULL);
01121 
01122     <span class="comment">/* we need ppc just in prefork mode */</span>
01123     <span class="keywordflow">if</span>(be-&gt;<a class="code" href="structbackend__s.html#o7">model</a> != SERVER_MODEL_PREFORK)
01124     {
01125         dbg_err_if(<a class="code" href="klog_8h.html#a28">klog_getln</a>(kl, i, line));
01126         <span class="keywordflow">return</span> 0;
01127     }
01128 
01129     <span class="comment">/* send the ppc command and read back the response */</span>
01130     nop_err_if(<a class="code" href="server__ppc__cmd_8h.html#a7">server_ppc_cmd_log_get</a>(s, i, line));
01131 
01132     <span class="keywordflow">return</span> 0;
01133 err:
01134     <span class="keywordflow">return</span> ~0;
01135 }
01136 
<a name="l01137"></a><a class="code" href="server_8h.html#a18">01137</a> <span class="keywordtype">int</span> <a class="code" href="server_8h.html#a18">server_foreach_memlog_line</a>(<a class="code" href="structserver__s.html">server_t</a> *s, 
01138     <span class="keywordtype">int</span> (*cb)(<span class="keyword">const</span> <span class="keywordtype">char</span>*, <span class="keywordtype">void</span>*), <span class="keywordtype">void</span> *arg)
01139 {
01140     <a class="code" href="structklog__s.html">klog_t</a> *kl = NULL;  
01141     size_t i;
01142     <span class="keywordtype">char</span> line[KLOG_LN_SZ];
01143 
01144     <span class="comment">/* get the configured klog object and check that's a in-memory klog */</span>
01145     <span class="keywordflow">if</span>(<a class="code" href="server_8h.html#a17">server_get_logger</a>(s, &amp;kl) || kl == NULL || kl-&gt;<a class="code" href="structklog__s.html#o0">type</a> != KLOG_TYPE_MEM)
01146     {
01147         cb(<span class="stringliteral">"logging is not configured or is not a in-memory log"</span>, arg);
01148         <span class="keywordflow">return</span> ~0;
01149     }
01150 
01151     <span class="comment">/* for each log line call the user-given callback function */</span>
01152     <span class="keywordflow">for</span>(i = 1; server_get_klog_line(s, kl, i, line) == 0; ++i)
01153         cb(line, arg);
01154 
01155     <span class="keywordflow">return</span> 0;
01156 err:
01157     cb(<span class="stringliteral">"klog_getln error"</span>, arg);
01158     <span class="keywordflow">return</span> ~0;
01159 }
01160 
01161 
<a name="l01162"></a><a class="code" href="server__s_8h.html#a1">01162</a> <span class="keywordtype">int</span> <a class="code" href="server__s_8h.html#a1">server_get_backend_by_id</a>(<a class="code" href="structserver__s.html">server_t</a> *s, <span class="keywordtype">int</span> <span class="keywordtype">id</span>, <a class="code" href="structbackend__s.html">backend_t</a> **pbe)
01163 {
01164     <a class="code" href="structbackend__s.html">backend_t</a> *be;
01165 
01166     dbg_err_if (s == NULL);
01167     dbg_err_if (pbe == NULL);
01168     
01169     LIST_FOREACH(be, &amp;s-&gt;<a class="code" href="structserver__s.html#o2">bes</a>, np)
01170     {
01171         <span class="keywordflow">if</span>(be-&gt;<a class="code" href="structbackend__s.html#o11">id</a> == id)
01172         {
01173             *pbe = be;
01174             <span class="keywordflow">return</span> 0;
01175         }
01176     }
01177 
01178 err: <span class="comment">/* fall through if search loop exhausted */</span>
01179     <span class="keywordflow">return</span> ~0;
01180 }
01181 
<a name="l01182"></a><a class="code" href="server_8c.html#a32">01182</a> <span class="keywordtype">int</span> <a class="code" href="server_8h.html#a11">server_create</a>(u_config_t *config, <span class="keywordtype">int</span> foreground, <a class="code" href="structserver__s.html">server_t</a> **ps)
01183 {
01184     <a class="code" href="structserver__s.html">server_t</a> *s = NULL;
01185     u_config_t *bekey = NULL, *log_c = NULL;
01186     <a class="code" href="structbackend__s.html">backend_t</a> *be = NULL;
01187     <span class="keyword">const</span> <span class="keywordtype">char</span> *list, *type;
01188     <span class="keywordtype">char</span> *n = NULL, *name = NULL;
01189     <span class="keywordtype">int</span> i, id, iv;
01190 
01191     dbg_return_if (ps == NULL, ~0);
01192     dbg_return_if (config == NULL, ~0);
01193 
01194 <span class="preprocessor">#ifdef OS_WIN</span>
01195 <span class="preprocessor"></span>    WORD ver;
01196     WSADATA wsadata;
01197 
01198     ver = MAKEWORD(1,1);
01199     dbg_err_if(WSAStartup(ver, &amp;wsadata));
01200 <span class="preprocessor">#endif</span>
01201 <span class="preprocessor"></span>
01202     s = u_zalloc(<span class="keyword">sizeof</span>(<a class="code" href="structserver__s.html">server_t</a>));
01203     dbg_err_if(s == NULL);
01204 
01205     *ps = s; <span class="comment">/* we need it before backend inits */</span>
01206 
01207     s-&gt;<a class="code" href="structserver__s.html#o0">config</a> = config;
01208     s-&gt;<a class="code" href="structserver__s.html#o17">model</a> = SERVER_MODEL_FORK; <span class="comment">/* default */</span>
01209 
01210     dbg_err_if(<a class="code" href="child_8h.html#a7">children_create</a>(&amp;s-&gt;<a class="code" href="structserver__s.html#o5">children</a>));
01211 
01212     <span class="comment">/* init fd_set */</span>
01213     FD_ZERO(&amp;s-&gt;<a class="code" href="structserver__s.html#o6">rdfds</a>);
01214     FD_ZERO(&amp;s-&gt;<a class="code" href="structserver__s.html#o7">wrfds</a>);
01215     FD_ZERO(&amp;s-&gt;<a class="code" href="structserver__s.html#o8">exfds</a>);
01216 
01217     <span class="comment">/* init backend list */</span>
01218     LIST_INIT(&amp;s-&gt;<a class="code" href="structserver__s.html#o2">bes</a>);
01219 
01220     dbg_err_if(<a class="code" href="ppc_8h.html#a3">ppc_create</a>(&amp;s-&gt;<a class="code" href="structserver__s.html#o1">ppc</a>));
01221 
01222     <span class="comment">/* create the log device if requested */</span>
01223     <span class="keywordflow">if</span>(!u_config_get_subkey(config, <span class="stringliteral">"log"</span>, &amp;log_c))
01224     {
01225         dbg_if(<a class="code" href="klog_8h.html#a33">klog_open_from_config</a>(log_c, &amp;s-&gt;<a class="code" href="structserver__s.html#o3">klog</a>));
01226         s-&gt;<a class="code" href="structserver__s.html#o18">klog_flush</a> = 1;
01227     }
01228 
01229     <span class="comment">/* register the log ppc callbacks */</span>
01230     dbg_err_if(<a class="code" href="ppc_8h.html#a5">ppc_register</a>(s-&gt;<a class="code" href="structserver__s.html#o1">ppc</a>, <a class="code" href="ppc__cmd_8h.html#a11a1">PPC_CMD_NOP</a>, <a class="code" href="ppc__nop_8c.html#a2">server_ppc_cb_nop</a>, s));
01231     dbg_err_if(<a class="code" href="ppc_8h.html#a5">ppc_register</a>(s-&gt;<a class="code" href="structserver__s.html#o1">ppc</a>, <a class="code" href="ppc__cmd_8h.html#a11a9">PPC_CMD_LOG_ADD</a>, <a class="code" href="ppc__log__add_8c.html#a3">server_ppc_cb_log_add</a>, s));
01232     dbg_err_if(<a class="code" href="ppc_8h.html#a5">ppc_register</a>(s-&gt;<a class="code" href="structserver__s.html#o1">ppc</a>, <a class="code" href="ppc__cmd_8h.html#a11a10">PPC_CMD_LOG_GET</a>, <a class="code" href="ppc__log__get_8c.html#a2">server_ppc_cb_log_get</a>, s));
01233 <span class="preprocessor">#ifdef OS_UNIX</span>
01234 <span class="preprocessor"></span>    dbg_err_if(<a class="code" href="ppc_8h.html#a5">ppc_register</a>(s-&gt;<a class="code" href="structserver__s.html#o1">ppc</a>, <a class="code" href="ppc__cmd_8h.html#a11a2">PPC_CMD_FORK_CHILD</a>, 
01235         <a class="code" href="ppc__fork__child_8c.html#a2">server_ppc_cb_fork_child</a>, s));
01236 <span class="preprocessor">#endif</span>
01237 <span class="preprocessor"></span>
01238     <span class="comment">/* redirect logs to the server_log_hook function */</span>
01239     dbg_err_if(u_log_set_hook(server_log_hook, s, NULL, NULL));
01240 
01241     <span class="comment">/* parse server list and build s-&gt;bes */</span>
01242     list = u_config_get_subkey_value(config, <span class="stringliteral">"server_list"</span>);
01243     warn_err_ifm(list == NULL, <span class="stringliteral">"bad or missing 'server_list' config param"</span>);
01244 
01245     <span class="comment">/* chroot, uid and gid */</span>
01246     s-&gt;<a class="code" href="structserver__s.html#o9">chroot</a> = u_config_get_subkey_value(config, <span class="stringliteral">"chroot"</span>);
01247     dbg_err_if(u_config_get_subkey_value_i(config, <span class="stringliteral">"uid"</span>, -1, &amp;s-&gt;<a class="code" href="structserver__s.html#o10">uid</a>));
01248     dbg_err_if(u_config_get_subkey_value_i(config, <span class="stringliteral">"gid"</span>, -1, &amp;s-&gt;<a class="code" href="structserver__s.html#o11">gid</a>));
01249     dbg_err_if(u_config_get_subkey_value_b(config, <span class="stringliteral">"allow_root"</span>, 0, 
01250         &amp;s-&gt;<a class="code" href="structserver__s.html#o20">allow_root</a>));
01251     dbg_err_if(u_config_get_subkey_value_b(config, <span class="stringliteral">"blind_chroot"</span>, 0, 
01252         &amp;s-&gt;<a class="code" href="structserver__s.html#o21">blind_chroot</a>));
01253 
01254     warn_err_ifm(!s-&gt;<a class="code" href="structserver__s.html#o10">uid</a> || !s-&gt;<a class="code" href="structserver__s.html#o11">gid</a>, 
01255         <span class="stringliteral">"you must set uid and gid config parameters"</span>);
01256 
01257     dbg_err_if(u_config_get_subkey_value_i(config, <span class="stringliteral">"max_child"</span>, 
01258         <a class="code" href="server_8h.html#a19a2">SERVER_MAX_CHILD</a>, &amp;iv));
01259     s-&gt;<a class="code" href="structserver__s.html#o15">max_child</a> = iv;
01260 
01261     name = n = u_zalloc(strlen(list) + 1);
01262     dbg_err_if(name == NULL);
01263     
01264     <span class="comment">/* load config and init backend for each server in server.list */</span>
01265     <span class="keywordflow">for</span>(i = strlen(list), <span class="keywordtype">id</span> = 0; 
01266         i &gt; 0 &amp;&amp; sscanf(list, <span class="stringliteral">"%[^ \t]"</span>, name); 
01267         i -= 1 + strlen(name), list += 1 + strlen(name), name[0] = 0)
01268     {
01269         dbg(<span class="stringliteral">"configuring backend: %s"</span>, name);
01270 
01271         <span class="comment">/* just SERVER_MAX_BACKENDS supported */</span>
01272         warn_err_if(s-&gt;<a class="code" href="structserver__s.html#o13">nbackend</a> == <a class="code" href="server_8c.html#a0">SERVER_MAX_BACKENDS</a>);
01273 
01274         <span class="comment">/* get config tree of this backend */</span>
01275         warn_err_ifm(u_config_get_subkey(config, name, &amp;bekey),
01276             <span class="stringliteral">"missing [%s] backend configuration"</span>, name);
01277 
01278         type = u_config_get_subkey_value(bekey, <span class="stringliteral">"type"</span>);
01279         warn_err_ifm(type == NULL, <span class="stringliteral">"missing or bad '&lt;servname&gt;.type' value"</span>);
01280 
01281         <span class="comment">/* create a new backend and push into the be list */</span>
01282         warn_err_ifm(<a class="code" href="backend_8h.html#a5">backend_create</a>(type, bekey, &amp;be),
01283             <span class="stringliteral">"backend \"%s\" startup error"</span>, type);
01284 
01285         be-&gt;<a class="code" href="structbackend__s.html#o4">server</a> = s;
01286         be-&gt;<a class="code" href="structbackend__s.html#o5">config</a> = bekey;
01287         be-&gt;<a class="code" href="structbackend__s.html#o11">id</a> = <span class="keywordtype">id</span>++;
01288         <span class="keywordflow">if</span>(be-&gt;<a class="code" href="structbackend__s.html#o7">model</a> == SERVER_MODEL_UNSET)
01289             be-&gt;<a class="code" href="structbackend__s.html#o7">model</a> = s-&gt;<a class="code" href="structserver__s.html#o17">model</a>; <span class="comment">/* inherit server model */</span>
01290 
01291         <span class="keywordflow">if</span>(foreground)
01292             be-&gt;<a class="code" href="structbackend__s.html#o7">model</a> = SERVER_MODEL_ITERATIVE;
01293 
01294         <span class="comment">/* create the log device (may fail if logging is not configured) */</span>
01295         <span class="keywordflow">if</span>(!u_config_get_subkey(bekey, <span class="stringliteral">"log"</span>, &amp;log_c))
01296             dbg_if(<a class="code" href="klog_8h.html#a33">klog_open_from_config</a>(log_c, &amp;be-&gt;<a class="code" href="structbackend__s.html#o10">klog</a>));
01297 
01298 <span class="preprocessor">#ifdef OS_WIN</span>
01299 <span class="preprocessor"></span>        <span class="keywordflow">if</span>(be-&gt;<a class="code" href="structbackend__s.html#o7">model</a> != SERVER_MODEL_ITERATIVE)
01300             warn_err(<span class="stringliteral">"child-based server model is not "</span>
01301                      <span class="stringliteral">"yet supported on Windows"</span>);
01302 <span class="preprocessor">#endif</span>
01303 <span class="preprocessor"></span>
01304         LIST_INSERT_HEAD(&amp;s-&gt;<a class="code" href="structserver__s.html#o2">bes</a>, be, np);
01305 
01306         dbg_err_if(server_setup_backend(s, be));
01307     }
01308 
01309     U_FREE(n);
01310 
01311     <span class="comment">/* init done, set signal handlers */</span>
01312     dbg_err_if(<a class="code" href="group__u__t.html#ga40">u_signal</a>(SIGINT, server_sigint));
01313     dbg_err_if(<a class="code" href="group__u__t.html#ga40">u_signal</a>(SIGTERM, server_sigterm));
01314 <span class="preprocessor">#ifdef OS_UNIX </span>
01315 <span class="preprocessor"></span>    dbg_err_if(<a class="code" href="group__u__t.html#ga40">u_signal</a>(SIGPIPE, SIG_IGN));
01316     dbg_err_if(<a class="code" href="group__u__t.html#ga40">u_signal</a>(SIGCHLD, server_sigchld));
01317 <span class="preprocessor">#endif</span>
01318 <span class="preprocessor"></span>
01319     <span class="keywordflow">return</span> 0;
01320 err:
01321     warn(<span class="stringliteral">"server init error (config error?)"</span>);
01322     U_FREE(n);
01323     <span class="keywordflow">if</span>(s)
01324     {
01325         <a class="code" href="server_8h.html#a12">server_free</a>(s);
01326         *ps = NULL;
01327     }
01328     <span class="keywordflow">return</span> ~0;
01329 }
01330 
</pre></div><hr>
<div> 
  <div style="text-align:left">
    <a href="http://www.koanlogic.com/kl/cont/gb/html/products.html">&larr;Products</a>
  </div>
  <div style="text-align:center;">
    &copy; 2005-2006 - <a href="http://www.koanlogic.com">KoanLogic S.r.l.</a> - All rights reserved
  </div>
</div>

</body>
</html>