1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.3
4: Copyright (C) 1989-2011 Dr. BERTRAND Joël
5:
6: This file is part of RPL/2.
7:
8: RPL/2 is free software; you can redistribute it and/or modify it
9: under the terms of the CeCILL V2 License as published by the french
10: CEA, CNRS and INRIA.
11:
12: RPL/2 is distributed in the hope that it will be useful, but WITHOUT
13: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14: FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License
15: for more details.
16:
17: You should have received a copy of the CeCILL License
18: along with RPL/2. If not, write to info@cecill.info.
19: ================================================================================
20: */
21:
22:
23: #include "rpl-conv.h"
24:
25:
26: /*
27: ================================================================================
28: Fonction 'splash'
29: ================================================================================
30: Entrées :
31: --------------------------------------------------------------------------------
32: Sorties :
33: --------------------------------------------------------------------------------
34: Effets de bord : néant
35: ================================================================================
36: */
37:
38: void
39: instruction_splash(struct_processus *s_etat_processus)
40: {
41: real8 attente;
42:
43: struct_objet *s_objet;
44:
45: (*s_etat_processus).erreur_execution = d_ex;
46:
47: if ((*s_etat_processus).affichage_arguments == 'Y')
48: {
49: printf("\n SPLASH ");
50:
51: if ((*s_etat_processus).langue == 'F')
52: {
53: printf("(écran RPL/2)\n\n");
54: }
55: else
56: {
57: printf("(RPL/2 splash screen)\n\n");
58: }
59:
60: printf(" 1: %s, %s\n", d_INT, d_REL);
61:
62: return;
63: }
64: else if ((*s_etat_processus).test_instruction == 'Y')
65: {
66: (*s_etat_processus).nombre_arguments = -1;
67: return;
68: }
69:
70: if (test_cfsf(s_etat_processus, 31) == d_vrai)
71: {
72: if (empilement_pile_last(s_etat_processus, 1) == d_erreur)
73: {
74: return;
75: }
76: }
77:
78: if (depilement(s_etat_processus, &((*s_etat_processus).l_base_pile),
79: &s_objet) == d_erreur)
80: {
81: (*s_etat_processus).erreur_execution = d_ex_manque_argument;
82: return;
83: }
84:
85: if (((*s_objet).type == INT) ||
86: ((*s_objet).type == REL))
87: {
88: if ((*s_objet).type == INT)
89: {
90: attente = (real8) (*((integer8 *) (*s_objet).objet));
91: }
92: else
93: {
94: attente = (*((real8 *) (*s_objet).objet));
95: }
96:
97: if (attente < 0)
98: {
99: liberation(s_etat_processus, s_objet);
100:
101: (*s_etat_processus).erreur_execution = d_ex_argument_invalide;
102: return;
103: }
104:
105: encart(s_etat_processus, (unsigned long) (attente * 1E6));
106: }
107: else
108: {
109: liberation(s_etat_processus, s_objet);
110:
111: (*s_etat_processus).erreur_execution = d_ex_erreur_type_argument;
112: return;
113: }
114:
115: liberation(s_etat_processus, s_objet);
116:
117: return;
118: }
119:
120:
121: /*
122: ================================================================================
123: Fonction 'send'
124: ================================================================================
125: Entrées :
126: --------------------------------------------------------------------------------
127: Sorties :
128: --------------------------------------------------------------------------------
129: Effets de bord : néant
130: ================================================================================
131: */
132:
133: void
134: instruction_send(struct_processus *s_etat_processus)
135: {
136: pid_t pid;
137:
138: pthread_t tid;
139:
140: sig_atomic_t registre;
141:
142: ssize_t longueur_ecriture;
143:
144: struct_objet *s_objet;
145:
146: struct timespec attente;
147:
148: unsigned char tampon;
149:
150: (*s_etat_processus).erreur_execution = d_ex;
151:
152: if ((*s_etat_processus).affichage_arguments == 'Y')
153: {
154: printf("\n SEND ");
155:
156: if ((*s_etat_processus).langue == 'F')
157: {
158: printf("(envoi de données au processus père)\n\n");
159: }
160: else
161: {
162: printf("(send data to parent process)\n\n");
163: }
164:
165: printf(" 1: %s, %s, %s, %s, %s, %s,\n"
166: " %s, %s, %s, %s, %s,\n"
167: " %s, %s, %s, %s, %s\n",
168: d_INT, d_REL, d_CPL, d_VIN, d_VRL, d_VCX, d_MIN, d_MRL, d_MCX,
169: d_BIN, d_NOM, d_CHN, d_LST, d_ALG, d_RPN, d_TAB);
170:
171: return;
172: }
173: else if ((*s_etat_processus).test_instruction == 'Y')
174: {
175: (*s_etat_processus).nombre_arguments = -1;
176: return;
177: }
178:
179: if (test_cfsf(s_etat_processus, 31) == d_vrai)
180: {
181: if (empilement_pile_last(s_etat_processus, 1) == d_erreur)
182: {
183: return;
184: }
185: }
186:
187: if (depilement(s_etat_processus, &((*s_etat_processus).l_base_pile),
188: &s_objet) == d_erreur)
189: {
190: (*s_etat_processus).erreur_execution = d_ex_manque_argument;
191: return;
192: }
193:
194: if ((*s_etat_processus).presence_pipes == d_faux)
195: {
196: liberation(s_etat_processus, s_objet);
197:
198: (*s_etat_processus).erreur_execution = d_ex_absence_processus_pere;
199: return;
200: }
201:
202: if (((*s_objet).type != INT) &&
203: ((*s_objet).type != REL) &&
204: ((*s_objet).type != CPL) &&
205: ((*s_objet).type != VIN) &&
206: ((*s_objet).type != VRL) &&
207: ((*s_objet).type != VCX) &&
208: ((*s_objet).type != MIN) &&
209: ((*s_objet).type != MRL) &&
210: ((*s_objet).type != MCX) &&
211: ((*s_objet).type != BIN) &&
212: ((*s_objet).type != NOM) &&
213: ((*s_objet).type != CHN) &&
214: ((*s_objet).type != LST) &&
215: ((*s_objet).type != ALG) &&
216: ((*s_objet).type != RPN) &&
217: ((*s_objet).type != TBL))
218: {
219: liberation(s_etat_processus, s_objet);
220:
221: (*s_etat_processus).erreur_execution = d_ex_erreur_type_argument;
222: return;
223: }
224:
225: /*
226: * On signale au processus père qu'il y a un objet de plus
227: * dans le pipe de données.
228: */
229:
230: registre = (*s_etat_processus).var_volatile_traitement_retarde_stop;
231: (*s_etat_processus).var_volatile_traitement_retarde_stop = 1;
232:
233: if ((*s_etat_processus).processus_detache == d_vrai)
234: {
235: if ((*s_etat_processus).profilage == d_vrai)
236: {
237: profilage(s_etat_processus, "Interprocess communications (SEND)");
238:
239: if ((*s_etat_processus).erreur_systeme != d_es)
240: {
241: return;
242: }
243: }
244:
245: pid = -3;
246:
247: attente.tv_sec = 0;
248: attente.tv_nsec = GRANULARITE_us * 1000;
249:
250: # ifndef SEMAPHORES_NOMMES
251: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
252: # else
253: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
254: # endif
255: {
256: (*s_etat_processus).erreur_systeme = d_es_processus;
257: return;
258: }
259:
260: while((longueur_ecriture = write_atomic(s_etat_processus,
261: (*s_etat_processus).pipe_nombre_objets_attente,
262: &pid, sizeof(pid))) != sizeof(pid))
263: {
264: # ifndef SEMAPHORES_NOMMES
265: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
266: # else
267: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
268: # endif
269: {
270: if (errno != EINTR)
271: {
272: (*s_etat_processus).erreur_systeme = d_es_processus;
273: return;
274: }
275: }
276:
277: if (longueur_ecriture == -1)
278: {
279: if ((*s_etat_processus).profilage == d_vrai)
280: {
281: profilage(s_etat_processus, NULL);
282: }
283:
284: (*s_etat_processus).erreur_systeme = d_es_processus;
285: return;
286: }
287:
288: nanosleep(&attente, NULL);
289: INCR_GRANULARITE(attente.tv_nsec);
290:
291: # ifndef SEMAPHORES_NOMMES
292: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
293: # else
294: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
295: # endif
296: {
297: (*s_etat_processus).erreur_systeme = d_es_processus;
298: return;
299: }
300:
301: scrutation_interruptions(s_etat_processus);
302: }
303:
304: pid = getpid();
305:
306: attente.tv_sec = 0;
307: attente.tv_nsec = GRANULARITE_us * 1000;
308:
309: while((longueur_ecriture = write_atomic(s_etat_processus,
310: (*s_etat_processus).pipe_nombre_objets_attente,
311: &pid, sizeof(pid))) != sizeof(pid))
312: {
313: # ifndef SEMAPHORES_NOMMES
314: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
315: # else
316: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
317: # endif
318: {
319: if (errno != EINTR)
320: {
321: (*s_etat_processus).erreur_systeme = d_es_processus;
322: return;
323: }
324: }
325:
326: if (longueur_ecriture == -1)
327: {
328: if ((*s_etat_processus).profilage == d_vrai)
329: {
330: profilage(s_etat_processus, NULL);
331: }
332:
333: (*s_etat_processus).erreur_systeme = d_es_processus;
334: return;
335: }
336:
337: nanosleep(&attente, NULL);
338: INCR_GRANULARITE(attente.tv_nsec);
339:
340: # ifndef SEMAPHORES_NOMMES
341: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
342: # else
343: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
344: # endif
345: {
346: (*s_etat_processus).erreur_systeme = d_es_processus;
347: return;
348: }
349:
350: scrutation_interruptions(s_etat_processus);
351: }
352:
353: # ifndef SEMAPHORES_NOMMES
354: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
355: # else
356: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
357: # endif
358: {
359: if (errno != EINTR)
360: {
361: (*s_etat_processus).erreur_systeme = d_es_processus;
362: return;
363: }
364: }
365: }
366: else
367: {
368: if ((*s_etat_processus).profilage == d_vrai)
369: {
370: profilage(s_etat_processus, "Interthread communications (SEND)");
371:
372: if ((*s_etat_processus).erreur_systeme != d_es)
373: {
374: return;
375: }
376: }
377:
378: tid = -3;
379:
380: attente.tv_sec = 0;
381: attente.tv_nsec = GRANULARITE_us * 1000;
382:
383: # ifndef SEMAPHORES_NOMMES
384: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
385: # else
386: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
387: # endif
388: {
389: (*s_etat_processus).erreur_systeme = d_es_processus;
390: return;
391: }
392:
393: while((longueur_ecriture = write_atomic(s_etat_processus,
394: (*s_etat_processus).pipe_nombre_objets_attente,
395: &tid, sizeof(tid))) != sizeof(tid))
396: {
397: # ifndef SEMAPHORES_NOMMES
398: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
399: # else
400: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
401: # endif
402: {
403: (*s_etat_processus).erreur_systeme = d_es_processus;
404: return;
405: }
406:
407: if (longueur_ecriture == -1)
408: {
409: if ((*s_etat_processus).profilage == d_vrai)
410: {
411: profilage(s_etat_processus, NULL);
412: }
413:
414: (*s_etat_processus).erreur_systeme = d_es_processus;
415: return;
416: }
417:
418: nanosleep(&attente, NULL);
419: INCR_GRANULARITE(attente.tv_nsec);
420:
421: # ifndef SEMAPHORES_NOMMES
422: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
423: # else
424: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
425: # endif
426: {
427: (*s_etat_processus).erreur_systeme = d_es_processus;
428: return;
429: }
430:
431: scrutation_interruptions(s_etat_processus);
432: }
433:
434: tid = pthread_self();
435:
436: attente.tv_sec = 0;
437: attente.tv_nsec = GRANULARITE_us * 1000;
438:
439: while((longueur_ecriture = write_atomic(s_etat_processus,
440: (*s_etat_processus).pipe_nombre_objets_attente,
441: &tid, sizeof(tid))) != sizeof(tid))
442: {
443: # ifndef SEMAPHORES_NOMMES
444: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
445: # else
446: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
447: # endif
448: {
449: if (errno != EINTR)
450: {
451: (*s_etat_processus).erreur_systeme = d_es_processus;
452: return;
453: }
454: }
455:
456: if (longueur_ecriture == -1)
457: {
458: if ((*s_etat_processus).profilage == d_vrai)
459: {
460: profilage(s_etat_processus, NULL);
461: }
462:
463: (*s_etat_processus).erreur_systeme = d_es_processus;
464: return;
465: }
466:
467: nanosleep(&attente, NULL);
468: INCR_GRANULARITE(attente.tv_nsec);
469:
470: # ifndef SEMAPHORES_NOMMES
471: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
472: # else
473: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
474: # endif
475: {
476: (*s_etat_processus).erreur_systeme = d_es_processus;
477: return;
478: }
479:
480: scrutation_interruptions(s_etat_processus);
481: }
482:
483: # ifndef SEMAPHORES_NOMMES
484: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
485: # else
486: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
487: # endif
488: {
489: (*s_etat_processus).erreur_systeme = d_es_processus;
490: return;
491: }
492: }
493:
494: (*s_etat_processus).nombre_objets_envoyes_non_lus++;
495:
496: attente.tv_sec = 0;
497: attente.tv_nsec = GRANULARITE_us * 1000;
498:
499: # ifndef SEMAPHORES_NOMMES
500: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
501: # else
502: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
503: # endif
504: {
505: (*s_etat_processus).erreur_systeme = d_es_processus;
506: return;
507: }
508:
509: while(read_atomic(s_etat_processus, (*s_etat_processus).pipe_acquittement,
510: &tampon, sizeof(unsigned char)) != sizeof(unsigned char))
511: {
512: # ifndef SEMAPHORES_NOMMES
513: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
514: # else
515: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
516: # endif
517: {
518: if (errno != EINTR)
519: {
520: (*s_etat_processus).erreur_systeme = d_es_processus;
521: return;
522: }
523: }
524:
525: nanosleep(&attente, NULL);
526: INCR_GRANULARITE(attente.tv_nsec);
527:
528: # ifndef SEMAPHORES_NOMMES
529: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
530: # else
531: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
532: # endif
533: {
534: (*s_etat_processus).erreur_systeme = d_es_processus;
535: return;
536: }
537:
538: scrutation_interruptions(s_etat_processus);
539: }
540:
541: # ifndef SEMAPHORES_NOMMES
542: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
543: # else
544: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
545: # endif
546: {
547: if (errno != EINTR)
548: {
549: (*s_etat_processus).erreur_systeme = d_es_processus;
550: return;
551: }
552: }
553:
554: // Envoi d'un PID invalide (-1) pour ne pas bloquer le thread
555: // de surveillance.
556:
557: if ((*s_etat_processus).processus_detache == d_vrai)
558: {
559: pid = -1;
560:
561: attente.tv_sec = 0;
562: attente.tv_nsec = GRANULARITE_us * 1000;
563:
564: # ifndef SEMAPHORES_NOMMES
565: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
566: # else
567: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
568: # endif
569: {
570: (*s_etat_processus).erreur_systeme = d_es_processus;
571: return;
572: }
573:
574: while((longueur_ecriture = write_atomic(s_etat_processus,
575: (*s_etat_processus).pipe_nombre_interruptions_attente,
576: &pid, sizeof(pid))) != sizeof(pid))
577: {
578: # ifndef SEMAPHORES_NOMMES
579: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
580: # else
581: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
582: # endif
583: {
584: (*s_etat_processus).erreur_systeme = d_es_processus;
585: return;
586: }
587:
588: if (longueur_ecriture == -1)
589: {
590: if ((*s_etat_processus).profilage == d_vrai)
591: {
592: profilage(s_etat_processus, NULL);
593: }
594:
595: (*s_etat_processus).erreur_systeme = d_es_processus;
596: return;
597: }
598:
599: nanosleep(&attente, NULL);
600: INCR_GRANULARITE(attente.tv_nsec);
601:
602: # ifndef SEMAPHORES_NOMMES
603: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
604: # else
605: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
606: # endif
607: {
608: (*s_etat_processus).erreur_systeme = d_es_processus;
609: return;
610: }
611: }
612:
613: # ifndef SEMAPHORES_NOMMES
614: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
615: # else
616: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
617: # endif
618: {
619: if (errno != EINTR)
620: {
621: (*s_etat_processus).erreur_systeme = d_es_processus;
622: return;
623: }
624: }
625:
626: scrutation_interruptions(s_etat_processus);
627: }
628: else
629: {
630: tid = -1;
631:
632: attente.tv_sec = 0;
633: attente.tv_nsec = GRANULARITE_us * 1000;
634:
635: # ifndef SEMAPHORES_NOMMES
636: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
637: # else
638: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
639: # endif
640: {
641: (*s_etat_processus).erreur_systeme = d_es_processus;
642: return;
643: }
644:
645: while((longueur_ecriture = write_atomic(s_etat_processus,
646: (*s_etat_processus).pipe_nombre_interruptions_attente,
647: &tid, sizeof(tid))) != sizeof(tid))
648: {
649: # ifndef SEMAPHORES_NOMMES
650: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
651: # else
652: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
653: # endif
654: {
655: if (errno != EINTR)
656: {
657: (*s_etat_processus).erreur_systeme = d_es_processus;
658: return;
659: }
660: }
661:
662: if (longueur_ecriture == -1)
663: {
664: if ((*s_etat_processus).profilage == d_vrai)
665: {
666: profilage(s_etat_processus, NULL);
667: }
668:
669: (*s_etat_processus).erreur_systeme = d_es_processus;
670: return;
671: }
672:
673: nanosleep(&attente, NULL);
674: INCR_GRANULARITE(attente.tv_nsec);
675:
676: # ifndef SEMAPHORES_NOMMES
677: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
678: # else
679: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
680: # endif
681: {
682: (*s_etat_processus).erreur_systeme = d_es_processus;
683: return;
684: }
685:
686: scrutation_interruptions(s_etat_processus);
687: }
688:
689: # ifndef SEMAPHORES_NOMMES
690: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
691: # else
692: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
693: # endif
694: {
695: if (errno != EINTR)
696: {
697: (*s_etat_processus).erreur_systeme = d_es_processus;
698: return;
699: }
700: }
701: }
702:
703: // ecriture_pipe() ne peut être interrompu par un signal.
704:
705: # ifndef SEMAPHORES_NOMMES
706: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
707: # else
708: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
709: # endif
710: {
711: (*s_etat_processus).erreur_systeme = d_es_processus;
712: return;
713: }
714:
715: if (ecriture_pipe(s_etat_processus, (*s_etat_processus).pipe_donnees,
716: s_objet) == d_erreur)
717: {
718: # ifndef SEMAPHORES_NOMMES
719: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
720: # else
721: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
722: # endif
723: {
724: if (errno != EINTR)
725: {
726: (*s_etat_processus).erreur_systeme = d_es_processus;
727: return;
728: }
729: }
730:
731: if ((*s_etat_processus).profilage == d_vrai)
732: {
733: profilage(s_etat_processus, NULL);
734: }
735:
736: liberation(s_etat_processus, s_objet);
737: return;
738: }
739:
740: # ifndef SEMAPHORES_NOMMES
741: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
742: # else
743: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
744: # endif
745: {
746: if (errno != EINTR)
747: {
748: (*s_etat_processus).erreur_systeme = d_es_processus;
749: return;
750: }
751: }
752:
753: if ((*s_etat_processus).profilage == d_vrai)
754: {
755: profilage(s_etat_processus, NULL);
756: }
757:
758: if (registre == 0)
759: {
760: if ((*s_etat_processus).var_volatile_traitement_retarde_stop == -1)
761: {
762: (*s_etat_processus).var_volatile_requete_arret = -1;
763: }
764:
765: (*s_etat_processus).var_volatile_traitement_retarde_stop = registre;
766: }
767:
768: liberation(s_etat_processus, s_objet);
769: return;
770: }
771:
772:
773: /*
774: ================================================================================
775: Fonction 'sqlquery'
776: ================================================================================
777: Entrées :
778: --------------------------------------------------------------------------------
779: Sorties :
780: --------------------------------------------------------------------------------
781: Effets de bord : néant
782: ================================================================================
783: */
784:
785: void
786: instruction_sqlquery(struct_processus *s_etat_processus)
787: {
788: # define d_LONGUEUR 1024
789:
790: logical1 connexion_permanente;
791: logical1 presence_resultat;
792:
793: struct_objet *s_copie_1;
794: struct_objet *s_objet_1;
795: struct_objet *s_copie_2;
796: struct_objet *s_objet_2;
797: struct_objet *s_objet_resultat;
798:
799: struct_liste_chainee *l_element_courant;
800: struct_liste_chainee *l_element_courant_ligne;
801:
802: unsigned char *tampon;
803:
804: unsigned int i;
805: unsigned int j;
806: unsigned int nombre_colonnes;
807: unsigned int nombre_lignes;
808:
809: (*s_etat_processus).erreur_execution = d_ex;
810:
811: if ((*s_etat_processus).affichage_arguments == 'Y')
812: {
813: printf("\n SQLQUERY ");
814:
815: if ((*s_etat_processus).langue == 'F')
816: {
817: printf("(requête SQL)\n\n");
818: }
819: else
820: {
821: printf("(SQL query)\n\n");
822: }
823:
824: printf(" 2: %s\n", d_CHN);
825: printf(" 1: %s\n", d_LST);
826: printf("-> 1: %s\n\n", d_LST);
827:
828: printf(" 2: %s\n", d_CHN);
829: printf(" 1: %s\n", d_SQL);
830: printf("-> 1: %s\n\n", d_LST);
831:
832: if ((*s_etat_processus).langue == 'F')
833: {
834: printf(" Utilisation :\n\n");
835: }
836: else
837: {
838: printf(" Usage:\n\n");
839: }
840:
841: printf(" \"select * from table\"\n");
842: printf(" { \"mysql\" \"server\" \"database\" "
843: "\"user\" \"password\" } SQLQUERY\n");
844: printf(" \"select field from table\"\n");
845: printf(" { \"postgresql:iso-8859-1\" \"server\" "
846: "\"database\" \"user\" \"password\" port }\n");
847: printf(" SQLQUERY\n");
848:
849: return;
850: }
851: else if ((*s_etat_processus).test_instruction == 'Y')
852: {
853: (*s_etat_processus).nombre_arguments = -1;
854: return;
855: }
856:
857: if (test_cfsf(s_etat_processus, 31) == d_vrai)
858: {
859: if (empilement_pile_last(s_etat_processus, 2) == d_erreur)
860: {
861: return;
862: }
863: }
864:
865: if (depilement(s_etat_processus, &((*s_etat_processus).l_base_pile),
866: &s_objet_1) == d_erreur)
867: {
868: (*s_etat_processus).erreur_execution = d_ex_manque_argument;
869: return;
870: }
871:
872: if (depilement(s_etat_processus, &((*s_etat_processus).l_base_pile),
873: &s_objet_2) == d_erreur)
874: {
875: liberation(s_etat_processus, s_objet_1);
876:
877: (*s_etat_processus).erreur_execution = d_ex_manque_argument;
878: return;
879: }
880:
881: if ((*s_objet_1).type == LST)
882: {
883: connexion_permanente = d_faux;
884:
885: s_copie_1 = s_objet_1;
886:
887: if ((s_objet_1 = parametres_sql(s_etat_processus, s_copie_1)) == NULL)
888: {
889: liberation(s_etat_processus, s_copie_1);
890: liberation(s_etat_processus, s_objet_2);
891: return;
892: }
893:
894: liberation(s_etat_processus, s_copie_1);
895: }
896: else
897: {
898: if ((*s_objet_1).type == SQL)
899: {
900: if (((*((struct_connecteur_sql *) (*s_objet_1).objet)).pid !=
901: getpid()) || (pthread_equal((*((struct_connecteur_sql *)
902: (*s_objet_1).objet)).tid, pthread_self()) == 0))
903: {
904: (*s_etat_processus).erreur_execution =
905: d_ex_fichier_hors_contexte;
906:
907: liberation(s_etat_processus, s_objet_1);
908: liberation(s_etat_processus, s_objet_2);
909: return;
910: }
911: }
912:
913: connexion_permanente = d_vrai;
914: }
915:
916: if (((*s_objet_1).type == SQL) && ((*s_objet_2).type == CHN))
917: {
918: if ((*((struct_connecteur_sql *) (*s_objet_1).objet)).locale != NULL)
919: {
920: /*
921: * Transcodage de la commande SQL
922: */
923:
924: if ((s_copie_2 = copie_objet(s_etat_processus, s_objet_2, 'O'))
925: == NULL)
926: {
927: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
928: return;
929: }
930:
931: liberation(s_etat_processus, s_objet_2);
932: s_objet_2 = s_copie_2;
933:
934: tampon = (*s_objet_2).objet;
935:
936: if (((*s_objet_2).objet = transliteration(s_etat_processus, tampon,
937: (*((struct_connecteur_sql *) (*s_objet_1).objet)).locale,
938: d_locale)) == NULL)
939: {
940: return;
941: }
942:
943: free(tampon);
944: }
945:
946: /*
947: * Pilote MySQL
948: */
949:
950: if (strcmp((*((struct_connecteur_sql *) (*s_objet_1).objet)).type,
951: "MYSQL") == 0)
952: {
953: # ifdef MYSQL_SUPPORT
954:
955: MYSQL_RES *resultat_mysql;
956: MYSQL_ROW ligne;
957:
958: if (mysql_real_query((*((struct_connecteur_sql *) (*s_objet_1)
959: .objet)).descripteur.mysql, (unsigned char *) (*s_objet_2)
960: .objet, strlen((unsigned char *) (*s_objet_2).objet)) != 0)
961: {
962: if (connexion_permanente == d_faux)
963: {
964: mysql_close((*((struct_connecteur_sql *) (*s_objet_1)
965: .objet)).descripteur.mysql);
966: }
967:
968: liberation(s_etat_processus, s_objet_1);
969: liberation(s_etat_processus, s_objet_2);
970:
971: (*s_etat_processus).erreur_execution = d_ex_erreur_sql;
972: return;
973: }
974:
975: if ((resultat_mysql = mysql_store_result(
976: (*((struct_connecteur_sql *) (*s_objet_1).objet))
977: .descripteur.mysql)) == NULL)
978: {
979: // La requête ne renvoie rien (exemple : INSERT)
980: presence_resultat = d_faux;
981: nombre_colonnes = 0;
982: }
983: else
984: {
985: // La requête renvoie une ou plusieurs valeurs.
986: presence_resultat = d_vrai;
987: nombre_colonnes = mysql_field_count((*((struct_connecteur_sql *)
988: (*s_objet_1).objet)).descripteur.mysql);
989: }
990:
991: if ((s_objet_resultat = allocation(s_etat_processus, LST))
992: == NULL)
993: {
994: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
995: return;
996: }
997:
998: (*s_objet_resultat).objet = NULL;
999: l_element_courant = (*s_objet_resultat).objet;
1000:
1001: while(((presence_resultat == d_vrai) ?
1002: (ligne = mysql_fetch_row(resultat_mysql)) : NULL) != NULL)
1003: {
1004: unsigned long *longueurs;
1005:
1006: longueurs = mysql_fetch_lengths(resultat_mysql);
1007:
1008: if (l_element_courant == NULL)
1009: {
1010: if (((*s_objet_resultat).objet =
1011: allocation_maillon(s_etat_processus)) == NULL)
1012: {
1013: (*s_etat_processus).erreur_systeme =
1014: d_es_allocation_memoire;
1015: return;
1016: }
1017:
1018: l_element_courant = (struct_liste_chainee *)
1019: (*s_objet_resultat).objet;
1020: }
1021: else
1022: {
1023: if (((*l_element_courant).suivant =
1024: allocation_maillon(s_etat_processus)) == NULL)
1025: {
1026: (*s_etat_processus).erreur_systeme =
1027: d_es_allocation_memoire;
1028: return;
1029: }
1030:
1031: l_element_courant = (*l_element_courant).suivant;
1032: }
1033:
1034: (*l_element_courant).suivant = NULL;
1035:
1036: if (((*l_element_courant).donnee = allocation(s_etat_processus,
1037: LST)) == NULL)
1038: {
1039: (*s_etat_processus).erreur_systeme =
1040: d_es_allocation_memoire;
1041: return;
1042: }
1043:
1044: (*(*l_element_courant).donnee).objet = NULL;
1045: l_element_courant_ligne = NULL;
1046:
1047: for(i = 0; i < nombre_colonnes; i++)
1048: {
1049: if (l_element_courant_ligne == NULL)
1050: {
1051: if (((*(*l_element_courant).donnee).objet =
1052: allocation_maillon(s_etat_processus)) == NULL)
1053: {
1054: (*s_etat_processus).erreur_systeme =
1055: d_es_allocation_memoire;
1056: return;
1057: }
1058:
1059: l_element_courant_ligne = (struct_liste_chainee *)
1060: (*(*l_element_courant).donnee).objet;
1061: }
1062: else
1063: {
1064: if (((*l_element_courant_ligne).suivant =
1065: allocation_maillon(s_etat_processus)) == NULL)
1066: {
1067: (*s_etat_processus).erreur_systeme =
1068: d_es_allocation_memoire;
1069: return;
1070: }
1071:
1072: l_element_courant_ligne =
1073: (*l_element_courant_ligne).suivant;
1074: }
1075:
1076: (*l_element_courant_ligne).suivant = NULL;
1077:
1078: if (((*l_element_courant_ligne).donnee =
1079: allocation(s_etat_processus, CHN)) == NULL)
1080: {
1081: (*s_etat_processus).erreur_systeme =
1082: d_es_allocation_memoire;
1083: return;
1084: }
1085:
1086: if (ligne[i] == NULL)
1087: {
1088: if (((*(*l_element_courant_ligne).donnee).objet =
1089: malloc(5 * sizeof(unsigned char))) == NULL)
1090: {
1091: (*s_etat_processus).erreur_systeme =
1092: d_es_allocation_memoire;
1093: return;
1094: }
1095:
1096: strcpy((unsigned char *) (*(*l_element_courant_ligne)
1097: .donnee).objet, "NULL");
1098: }
1099: else
1100: {
1101: if (((*(*l_element_courant_ligne).donnee).objet =
1102: malloc((longueurs[i] + 1) *
1103: sizeof(unsigned char))) == NULL)
1104: {
1105: (*s_etat_processus).erreur_systeme =
1106: d_es_allocation_memoire;
1107: return;
1108: }
1109:
1110: strcpy((unsigned char *) (*(*l_element_courant_ligne)
1111: .donnee).objet, ligne[i]);
1112: }
1113: }
1114: }
1115:
1116: mysql_free_result(resultat_mysql);
1117:
1118: if (connexion_permanente == d_faux)
1119: {
1120: mysql_close((*((struct_connecteur_sql *) (*s_objet_1).objet))
1121: .descripteur.mysql);
1122: }
1123:
1124: if (presence_resultat == d_vrai)
1125: {
1126: if (empilement(s_etat_processus,
1127: &((*s_etat_processus).l_base_pile),
1128: s_objet_resultat) == d_erreur)
1129: {
1130: return;
1131: }
1132: }
1133:
1134: # else
1135:
1136: if ((*s_etat_processus).langue == 'F')
1137: {
1138: printf("+++Attention : Support de MySQL non compilé !\n");
1139: }
1140: else
1141: {
1142: printf("+++Warning : MySQL support not available !\n");
1143: }
1144:
1145: fflush(stdout);
1146: # endif
1147: }
1148:
1149: /*
1150: * Pilote PostgreSQL
1151: */
1152:
1153: else if (strcmp((*((struct_connecteur_sql *) (*s_objet_1).objet)).type,
1154: "POSTGRESQL") == 0)
1155: {
1156: # ifdef POSTGRESQL_SUPPORT
1157:
1158: PGresult *resultat_postgresql;
1159:
1160: if (PQstatus((*((struct_connecteur_sql *) (*s_objet_1).objet))
1161: .descripteur.postgresql) != CONNECTION_OK)
1162: {
1163: if (connexion_permanente == d_faux)
1164: {
1165: PQfinish((*((struct_connecteur_sql *) (*s_objet_1).objet))
1166: .descripteur.postgresql);
1167: }
1168:
1169: liberation(s_etat_processus, s_objet_1);
1170: liberation(s_etat_processus, s_objet_2);
1171:
1172: (*s_etat_processus).erreur_execution = d_ex_erreur_sql;
1173: return;
1174: }
1175:
1176: resultat_postgresql = PQexec((*((struct_connecteur_sql *)
1177: (*s_objet_1).objet)).descripteur.postgresql,
1178: (unsigned char *) (*s_objet_2).objet);
1179: presence_resultat = d_faux;
1180:
1181: switch(PQresultStatus(resultat_postgresql))
1182: {
1183: case PGRES_COMMAND_OK :
1184: { // Commande qui ne renvoit rien
1185: if ((s_objet_resultat = allocation(s_etat_processus, LST))
1186: == NULL)
1187: {
1188: (*s_etat_processus).erreur_systeme =
1189: d_es_allocation_memoire;
1190: return;
1191: }
1192:
1193: (*s_objet_resultat).objet = NULL;
1194: l_element_courant = (*s_objet_resultat).objet;
1195: presence_resultat = d_vrai;
1196:
1197: break;
1198: }
1199:
1200: case PGRES_TUPLES_OK :
1201: { // Commande renvoyant des données
1202: if ((s_objet_resultat = allocation(s_etat_processus, LST))
1203: == NULL)
1204: {
1205: (*s_etat_processus).erreur_systeme =
1206: d_es_allocation_memoire;
1207: return;
1208: }
1209:
1210: (*s_objet_resultat).objet = NULL;
1211: l_element_courant = (*s_objet_resultat).objet;
1212: presence_resultat = d_vrai;
1213:
1214: nombre_colonnes = PQnfields(resultat_postgresql);
1215: nombre_lignes = PQntuples(resultat_postgresql);
1216:
1217: for(i = 0; i < nombre_lignes; i++)
1218: {
1219: // Chaînage d'un nouveau maillon de la liste résultat
1220:
1221: if (l_element_courant == NULL)
1222: {
1223: if (((*s_objet_resultat).objet =
1224: allocation_maillon(s_etat_processus))
1225: == NULL)
1226: {
1227: (*s_etat_processus).erreur_systeme =
1228: d_es_allocation_memoire;
1229: return;
1230: }
1231:
1232: l_element_courant = (struct_liste_chainee *)
1233: (*s_objet_resultat).objet;
1234: }
1235: else
1236: {
1237: if (((*l_element_courant).suivant =
1238: allocation_maillon(s_etat_processus))
1239: == NULL)
1240: {
1241: (*s_etat_processus).erreur_systeme =
1242: d_es_allocation_memoire;
1243: return;
1244: }
1245:
1246: l_element_courant = (*l_element_courant).suivant;
1247: }
1248:
1249: (*l_element_courant).suivant = NULL;
1250:
1251: // Création de la liste fille
1252:
1253: if (((*l_element_courant).donnee =
1254: allocation(s_etat_processus, LST)) == NULL)
1255: {
1256: (*s_etat_processus).erreur_systeme =
1257: d_es_allocation_memoire;
1258: return;
1259: }
1260:
1261: (*(*l_element_courant).donnee).objet = NULL;
1262: l_element_courant_ligne = NULL;
1263:
1264: for(j = 0; j < nombre_colonnes; j++)
1265: {
1266: if (l_element_courant_ligne == NULL)
1267: {
1268: if (((*(*l_element_courant).donnee).objet =
1269: allocation_maillon(s_etat_processus))
1270: == NULL)
1271: {
1272: (*s_etat_processus).erreur_systeme =
1273: d_es_allocation_memoire;
1274: return;
1275: }
1276:
1277: l_element_courant_ligne =
1278: (struct_liste_chainee *)
1279: (*(*l_element_courant).donnee).objet;
1280: }
1281: else
1282: {
1283: if (((*l_element_courant_ligne).suivant =
1284: allocation_maillon(s_etat_processus))
1285: == NULL)
1286: {
1287: l_element_courant_ligne =
1288: (*l_element_courant_ligne).suivant;
1289: }
1290:
1291: l_element_courant_ligne =
1292: (*l_element_courant_ligne).suivant;
1293: }
1294:
1295: (*l_element_courant_ligne).suivant = NULL;
1296:
1297: if (((*l_element_courant_ligne).donnee =
1298: allocation(s_etat_processus, CHN))
1299: == NULL)
1300: {
1301: (*s_etat_processus).erreur_systeme =
1302: d_es_allocation_memoire;
1303: return;
1304: }
1305:
1306: if (PQgetisnull(resultat_postgresql, i, j) != 0)
1307: {
1308: if (((*(*l_element_courant_ligne).donnee).objet
1309: = malloc(5 * sizeof(unsigned char)))
1310: == NULL)
1311: {
1312: (*s_etat_processus).erreur_systeme =
1313: d_es_allocation_memoire;
1314: return;
1315: }
1316:
1317: strcpy((unsigned char *)
1318: (*(*l_element_courant_ligne).donnee)
1319: .objet, "NULL");
1320: }
1321: else
1322: {
1323: if (((*(*l_element_courant_ligne).donnee).objet
1324: = malloc((PQgetlength(
1325: resultat_postgresql, i, j) + 1) *
1326: sizeof(unsigned char))) == NULL)
1327: {
1328: (*s_etat_processus).erreur_systeme =
1329: d_es_allocation_memoire;
1330: return;
1331: }
1332:
1333: strcpy((unsigned char *)
1334: (*(*l_element_courant_ligne).donnee)
1335: .objet, PQgetvalue(resultat_postgresql,
1336: i, j));
1337: }
1338: }
1339: }
1340:
1341: break;
1342: }
1343:
1344: case PGRES_EMPTY_QUERY :
1345: case PGRES_COPY_OUT :
1346: case PGRES_COPY_IN :
1347: case PGRES_BAD_RESPONSE :
1348: case PGRES_NONFATAL_ERROR :
1349: case PGRES_FATAL_ERROR :
1350: default :
1351: {
1352: printf("%s\n", PQresultErrorMessage(resultat_postgresql));
1353: PQclear(resultat_postgresql);
1354:
1355: if (connexion_permanente == d_faux)
1356: {
1357: PQfinish((*((struct_connecteur_sql *) (*s_objet_1)
1358: .objet)).descripteur.postgresql);
1359: }
1360:
1361: liberation(s_etat_processus, s_objet_1);
1362: liberation(s_etat_processus, s_objet_2);
1363:
1364: (*s_etat_processus).erreur_execution = d_ex_erreur_sql;
1365:
1366: return;
1367: break;
1368: }
1369: }
1370:
1371: PQclear(resultat_postgresql);
1372:
1373: if (connexion_permanente == d_faux)
1374: {
1375: PQfinish((*((struct_connecteur_sql *) (*s_objet_1).objet))
1376: .descripteur.postgresql);
1377: }
1378:
1379: if (presence_resultat == d_vrai)
1380: {
1381: if (empilement(s_etat_processus, &((*s_etat_processus)
1382: .l_base_pile), s_objet_resultat) == d_erreur)
1383: {
1384: return;
1385: }
1386: }
1387:
1388: # else
1389:
1390: if ((*s_etat_processus).langue == 'F')
1391: {
1392: printf("+++Attention : Support de PostgreSQL non compilé !\n");
1393: }
1394: else
1395: {
1396: printf("+++Warning : PostgreSQL support not available !\n");
1397: }
1398:
1399: fflush(stdout);
1400: # endif
1401: }
1402: else
1403: {
1404: liberation(s_etat_processus, s_objet_1);
1405: liberation(s_etat_processus, s_objet_2);
1406:
1407: (*s_etat_processus).erreur_execution = d_ex_erreur_sql;
1408: return;
1409: }
1410: }
1411: else
1412: {
1413: liberation(s_etat_processus, s_objet_1);
1414: liberation(s_etat_processus, s_objet_2);
1415:
1416: (*s_etat_processus).erreur_execution = d_ex_erreur_type_argument;
1417: return;
1418: }
1419:
1420: liberation(s_etat_processus, s_objet_1);
1421: liberation(s_etat_processus, s_objet_2);
1422:
1423: return;
1424: }
1425:
1426:
1427: /*
1428: ================================================================================
1429: Fonction 'stop'
1430: ================================================================================
1431: Entrées :
1432: --------------------------------------------------------------------------------
1433: Sorties :
1434: --------------------------------------------------------------------------------
1435: Effets de bord : néant
1436: ================================================================================
1437: */
1438:
1439: void
1440: instruction_stop(struct_processus *s_etat_processus)
1441: {
1442: struct_liste_chainee *l_element_courant;
1443:
1444: struct_objet *s_objet;
1445:
1446: (*s_etat_processus).erreur_execution = d_ex;
1447:
1448: if ((*s_etat_processus).affichage_arguments == 'Y')
1449: {
1450: printf("\n STOP ");
1451:
1452: if ((*s_etat_processus).langue == 'F')
1453: {
1454: printf("(arrêt d'un processus)\n\n");
1455: }
1456: else
1457: {
1458: printf("(kill process)\n\n");
1459: }
1460:
1461: printf(" 1: %s\n", d_PRC);
1462:
1463: return;
1464: }
1465: else if ((*s_etat_processus).test_instruction == 'Y')
1466: {
1467: (*s_etat_processus).nombre_arguments = -1;
1468: return;
1469: }
1470:
1471: if (test_cfsf(s_etat_processus, 31) == d_vrai)
1472: {
1473: if (empilement_pile_last(s_etat_processus, 1) == d_erreur)
1474: {
1475: return;
1476: }
1477: }
1478:
1479: if (depilement(s_etat_processus, &((*s_etat_processus).l_base_pile),
1480: &s_objet) == d_erreur)
1481: {
1482: (*s_etat_processus).erreur_execution = d_ex_manque_argument;
1483: return;
1484: }
1485:
1486: if ((*s_objet).type == PRC)
1487: {
1488: if ((*(*((struct_processus_fils *) (*s_objet).objet)).thread)
1489: .processus_detache == d_vrai)
1490: {
1491: envoi_signal_processus((*(*((struct_processus_fils *)
1492: (*s_objet).objet)).thread).pid, rpl_sigstop);
1493: }
1494: else
1495: {
1496: if (pthread_mutex_lock(&((*s_etat_processus).mutex)) != 0)
1497: {
1498: (*s_etat_processus).erreur_systeme = d_es_processus;
1499: return;
1500: }
1501:
1502: l_element_courant = (struct_liste_chainee *)
1503: (*s_etat_processus).l_base_pile_processus;
1504:
1505: while(l_element_courant != NULL)
1506: {
1507: if ((*(*((struct_processus_fils *) (*(*l_element_courant)
1508: .donnee).objet)).thread).processus_detache == d_faux)
1509: {
1510: if ((pthread_equal((*(*((struct_processus_fils *)
1511: (*(*l_element_courant).donnee).objet)).thread).tid,
1512: (*(*((struct_processus_fils *)
1513: (*s_objet).objet)).thread).tid) != 0) &&
1514: ((*(*((struct_processus_fils *)
1515: (*(*l_element_courant).donnee).objet)).thread).pid
1516: == (*(*((struct_processus_fils *)
1517: (*s_objet).objet)).thread).pid))
1518: {
1519: break;
1520: }
1521: }
1522:
1523: l_element_courant = (*l_element_courant).suivant;
1524: }
1525:
1526: if (l_element_courant != NULL)
1527: {
1528: // Le champ thread_actif est un pointeur sur un champ de la
1529: // structure s_argument_thread libéré par la fonction
1530: // retrait_thread_surveillance().
1531:
1532: if ((*(*((struct_processus_fils *)
1533: (*s_objet).objet)).thread).thread_actif == d_vrai)
1534: {
1535: if (pthread_mutex_lock(&((*(*((struct_processus_fils *)
1536: (*s_objet).objet)).thread).mutex)) != 0)
1537: {
1538: if (pthread_mutex_unlock(&((*s_etat_processus).mutex))
1539: != 0)
1540: {
1541: (*s_etat_processus).erreur_systeme = d_es_processus;
1542: return;
1543: }
1544:
1545: (*s_etat_processus).erreur_systeme = d_es_processus;
1546: return;
1547: }
1548:
1549: if ((*(*((struct_processus_fils *)
1550: (*s_objet).objet)).thread).thread_actif == d_vrai)
1551: {
1552: envoi_signal_thread((*(*((struct_processus_fils *)
1553: (*s_objet).objet)).thread).tid, rpl_sigstop);
1554: }
1555:
1556: if (pthread_mutex_unlock(&((*(*((struct_processus_fils *)
1557: (*s_objet).objet)).thread).mutex)) != 0)
1558: {
1559: if (pthread_mutex_unlock(&((*s_etat_processus).mutex))
1560: != 0)
1561: {
1562: (*s_etat_processus).erreur_systeme = d_es_processus;
1563: return;
1564: }
1565:
1566: (*s_etat_processus).erreur_systeme = d_es_processus;
1567: return;
1568: }
1569: }
1570: }
1571:
1572: if (pthread_mutex_unlock(&((*s_etat_processus).mutex)) != 0)
1573: {
1574: (*s_etat_processus).erreur_systeme = d_es_processus;
1575: return;
1576: }
1577: }
1578: }
1579: else
1580: {
1581: liberation(s_etat_processus, s_objet);
1582:
1583: (*s_etat_processus).erreur_execution = d_ex_erreur_type_argument;
1584: return;
1585: }
1586:
1587: liberation(s_etat_processus, s_objet);
1588:
1589: return;
1590: }
1591:
1592: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>