Skip the RV printing test under threads until fixed.
[p5sagit/p5-mst-13.2.git] / NetWare / Nwpipe.c
CommitLineData
2986a63f 1
2/*
3 * Copyright © 2001 Novell, Inc. All Rights Reserved.
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10/*
11 * FILENAME : NWPipe.c
12 * DESCRIPTION : Functions to implement pipes on NetWare.
13 * Author : HYAK
14 * Date : January 2001.
15 *
16 */
17
18
19
20#include <nwadv.h>
21#include <nwdsdefs.h>
22
23#include "win32ish.h"
24#include "nwpipe.h"
25#include "nwplglob.h"
26
27
28// This was added since the compile failed saying "undefined P_WAIT"
29// when USE_ITHREADS was commented in the makefile
30#ifndef P_WAIT
31#define P_WAIT 0
32#endif
33
34#ifndef P_NOWAIT
35#define P_NOWAIT 1
36#endif
37
38
39
40
41/*============================================================================================
42
43 Function : fnPipeFileMakeArgv
44
45 Description : This function makes the argument array.
46
47 Parameters : ptpf (IN) - Input structure.
48
49 Returns : Boolean.
50
51==============================================================================================*/
52
53BOOL fnPipeFileMakeArgv(PTEMPPIPEFILE ptpf)
54{
55 int i=0, j=0;
56 int dindex = 0;
57 int sindex = 0;
58
59 ptpf->m_argv_len = 0;
60
61
62 // Below 2 is added for the following reason:
63 // - The first one is for an additional value that will be added through ptpf->m_redirect.
64 // - The second one is for a NULL termination of the array.
65 // This is required for spawnvp API that takes a NULL-terminated array as its 3rd parameter.
66 // If the array is NOT NULL-terminated, then the server abends at the spawnvp call !!
67 ptpf->m_argv = (char **) malloc((ptpf->m_pipeCommand->m_argc + 2) * sizeof(char*));
68 if (ptpf->m_argv == NULL)
69 return FALSE;
70
71 // For memory allocation it is just +1 since the last one is only for NULL-termination
72 // and no memory is required to be allocated.
73 for(i=0; i<(ptpf->m_pipeCommand->m_argc + 1); i++)
74 {
75 ptpf->m_argv[i] = (char *) malloc(MAX_DN_BYTES * sizeof(char));
76 if (ptpf->m_argv[i] == NULL)
77 {
78 for(j=0; j<i; j++)
79 {
80 if(ptpf->m_argv[j])
81 {
82 free(ptpf->m_argv[j]);
83 ptpf->m_argv[j] = NULL;
84 }
85 }
86 free(ptpf->m_argv);
87 ptpf->m_argv = NULL;
88
89 return FALSE;
90 }
91 }
92
93 // Copy over parsed items, removing "load" keyword if necessary.
94 sindex = ((stricmp(ptpf->m_pipeCommand->m_argv[0], LOAD_COMMAND) == 0) ? 1 : 0);
95 while (sindex < ptpf->m_pipeCommand->m_argc)
96 {
97 strcpy(ptpf->m_argv[dindex], ptpf->m_pipeCommand->m_argv[sindex]);
98 dindex++;
99 sindex++;
100 }
101
102 if (stricmp(ptpf->m_argv[0], PERL_COMMAND_NAME) == 0) // If Perl is the first command.
103 {
104 ptpf->m_launchPerl = TRUE;
105
106 #ifdef MPK_ON
107 ptpf->m_perlSynchSemaphore = kSemaphoreAlloc((BYTE *)"pipeSemaphore", 0);
108 #else
109 ptpf->m_perlSynchSemaphore = OpenLocalSemaphore(0);
110 #endif //MPK_ON
111 }
112 else if (stricmp(ptpf->m_argv[0], (char *)"perlglob") == 0)
113 ptpf->m_doPerlGlob = TRUE;
114
115
116 // Create last argument, which will redirect to or from the temp file
117 if (!ptpf->m_doPerlGlob || ptpf->m_mode)
118 {
119 if (!ptpf->m_mode) // If read mode?
120 {
121 if (ptpf->m_launchPerl)
122 strcpy(ptpf->m_redirect, (char *)">");
123 else
124 strcpy(ptpf->m_redirect, (char *)"(CLIB_OPT)/>");
125 }
126 else
127 {
128 if (ptpf->m_launchPerl)
129 strcpy(ptpf->m_redirect, (char *)"<");
130 else
131 strcpy(ptpf->m_redirect, (char *)"(CLIB_OPT)/<");
132 }
133 strcat(ptpf->m_redirect, ptpf->m_fileName);
134
135 if (ptpf->m_launchPerl)
136 {
137 char tbuf[15] = {'\0'};
138 sprintf(tbuf, (char *)" -{%x", ptpf->m_perlSynchSemaphore);
139 strcat(ptpf->m_redirect, tbuf);
140 }
141
142 strcpy(ptpf->m_argv[dindex], (char*) ptpf->m_redirect);
143 dindex++;
144 }
145
146 if (dindex < (ptpf->m_pipeCommand->m_argc + 1))
147 {
148 if(ptpf->m_argv[dindex])
149 {
150 free(ptpf->m_argv[dindex]);
151 ptpf->m_argv[dindex] = NULL; // NULL termination - required for spawnvp call.
152 }
153 }
154
155 ptpf->m_argv_len = dindex; // Length of the argv array OR number of argv string values.
156 ptpf->m_argv[ptpf->m_argv_len] = NULL; // NULL termination - required for spawnvp call.
157
158
159 return TRUE;
160}
161
162
163/*============================================================================================
164
165 Function : fnPipeFileOpen
166
167 Description : This function opens the pipe file.
168
169 Parameters : ptpf (IN) - Input structure.
170 command (IN) - Input command string.
171 mode (IN) - Mode of opening.
172
173 Returns : File pointer.
174
175==============================================================================================*/
176
177FILE* fnPipeFileOpen(PTEMPPIPEFILE ptpf, char* command, char* mode)
178{
179 int i=0, j=0;
180
181 char tempName[_MAX_PATH] = {'\0'};
182
183
184 ptpf->m_fileName = (char *) malloc(_MAX_PATH * sizeof(char));
185 if(ptpf->m_fileName == NULL)
186 return NULL;
187
188 // The char array is emptied so that there is no junk characters.
189 strncpy(ptpf->m_fileName, "", (_MAX_PATH * sizeof(char)));
190
191
192 // Save off stuff
193 //
194 if(strchr(mode,'r') != 0)
195 ptpf->m_mode = FALSE; // Read mode
196 else if(strchr(mode,'w') != 0)
197 ptpf->m_mode = TRUE; // Write mode
198 else
199 {
200 if(ptpf->m_fileName != NULL)
201 {
202// if (strlen(ptpf->m_fileName))
203 if (ptpf->m_fileName)
204 unlink(ptpf->m_fileName);
205
206 free(ptpf->m_fileName);
207 ptpf->m_fileName = NULL;
208 }
209
210 return NULL;
211 }
212
213
214 ptpf->m_pipeCommand = (PCOMMANDLINEPARSER) malloc(sizeof(COMMANDLINEPARSER));
215 if (!ptpf->m_pipeCommand)
216 {
217// if (strlen(ptpf->m_fileName))
218 if (ptpf->m_fileName)
219 unlink(ptpf->m_fileName);
220
221 free(ptpf->m_fileName);
222 ptpf->m_fileName = NULL;
223
224 return NULL;
225 }
226
227 // Initialise the variables
228 ptpf->m_pipeCommand->m_isValid = TRUE;
229
230/****
231// Commented since these are not being used. Still retained here.
232// To be removed once things are proved to be working fine to a good confident level,
233
234 ptpf->m_pipeCommand->m_redirInName = NULL;
235 ptpf->m_pipeCommand->m_redirOutName = NULL;
236 ptpf->m_pipeCommand->m_redirErrName = NULL;
237 ptpf->m_pipeCommand->m_redirBothName = NULL;
238 ptpf->m_pipeCommand->nextarg = NULL;
239****/
240
241 ptpf->m_pipeCommand->sSkippedToken = NULL;
242 ptpf->m_pipeCommand->m_argv = NULL;
243 ptpf->m_pipeCommand->new_argv = NULL;
244
245 #ifdef MPK_ON
246 ptpf->m_pipeCommand->m_qSemaphore = NULL;
247 #else
248 ptpf->m_pipeCommand->m_qSemaphore = 0L;
249 #endif //MPK_ON
250
251 ptpf->m_pipeCommand->m_noScreen = 0;
252 ptpf->m_pipeCommand->m_AutoDestroy = 0;
253 ptpf->m_pipeCommand->m_argc = 0;
254 ptpf->m_pipeCommand->m_argv_len = 1;
255
256
257 ptpf->m_pipeCommand->m_argv = (char **) malloc(ptpf->m_pipeCommand->m_argv_len * sizeof(char *));
258 if (ptpf->m_pipeCommand->m_argv == NULL)
259 {
260 free(ptpf->m_pipeCommand);
261 ptpf->m_pipeCommand = NULL;
262
263// if (strlen(ptpf->m_fileName))
264 if (ptpf->m_fileName)
265 unlink(ptpf->m_fileName);
266
267 free(ptpf->m_fileName);
268 ptpf->m_fileName = NULL;
269
270 return NULL;
271 }
272 ptpf->m_pipeCommand->m_argv[0] = (char *) malloc(MAX_DN_BYTES * sizeof(char));
273 if (ptpf->m_pipeCommand->m_argv[0] == NULL)
274 {
275 for(j=0; j<i; j++)
276 {
277 if(ptpf->m_pipeCommand->m_argv[j])
278 {
279 free(ptpf->m_pipeCommand->m_argv[j]);
280 ptpf->m_pipeCommand->m_argv[j]=NULL;
281 }
282 }
283 free(ptpf->m_pipeCommand->m_argv);
284 ptpf->m_pipeCommand->m_argv=NULL;
285
286 free(ptpf->m_pipeCommand);
287 ptpf->m_pipeCommand = NULL;
288
289// if (strlen(ptpf->m_fileName))
290 if (ptpf->m_fileName)
291 unlink(ptpf->m_fileName);
292
293 free(ptpf->m_fileName);
294 ptpf->m_fileName = NULL;
295
296 return NULL;
297 }
298
299
300 ptpf->m_redirect = (char *) malloc(MAX_DN_BYTES * sizeof(char));
301 if (ptpf->m_redirect == NULL)
302 {
303 for(i=0; i<ptpf->m_pipeCommand->m_argv_len; i++)
304 {
305 if(ptpf->m_pipeCommand->m_argv[i] != NULL)
306 {
307 free(ptpf->m_pipeCommand->m_argv[i]);
308 ptpf->m_pipeCommand->m_argv[i] = NULL;
309 }
310 }
311
312 free(ptpf->m_pipeCommand->m_argv);
313 ptpf->m_pipeCommand->m_argv = NULL;
314
315 free(ptpf->m_pipeCommand);
316 ptpf->m_pipeCommand = NULL;
317
318
319// if (strlen(ptpf->m_fileName))
320 if (ptpf->m_fileName)
321 unlink(ptpf->m_fileName);
322
323 free(ptpf->m_fileName);
324 ptpf->m_fileName = NULL;
325
326 return NULL;
327 }
328
329 // The char array is emptied.
330 // If it is not done so, then it could contain some junk values and the string length in that case
331 // will not be zero. This causes erroneous results in fnPipeFileMakeArgv() function
332 // where strlen(ptpf->m_redirect) is used as a check for incrementing the parameter count and
333 // it will wrongly get incremented in such cases.
334 strncpy(ptpf->m_redirect, "", (MAX_DN_BYTES * sizeof(char)));
335
336 // Parse the parameters.
337 fnCommandLineParser(ptpf->m_pipeCommand, (char *)command, TRUE);
338 if (!ptpf->m_pipeCommand->m_isValid)
339 {
340 fnTempPipeFileReleaseMemory(ptpf);
341 return NULL;
342 }
343
344
345 // Create a temporary file name
346 //
1db1659f 347 strncpy ( tempName, fnNwGetEnvironmentStr((char *)"TEMP", NWDEFPERLTEMP), (_MAX_PATH - 20) );
2986a63f 348 tempName[_MAX_PATH-20] = '\0';
349 strcat(tempName, (char *)"\\plXXXXXX.tmp");
350 if (!fnMy_MkTemp(tempName))
351 {
352 fnTempPipeFileReleaseMemory(ptpf);
353 return NULL;
354 }
355
356 // create a temporary place-holder file
357 fclose(fopen(tempName, (char *)"w"));
358 strcpy(ptpf->m_fileName, tempName);
359
360
361 // Make the argument array
362 if(!fnPipeFileMakeArgv(ptpf))
363 {
364 fnTempPipeFileReleaseMemory(ptpf);
365
366 // Release additional memory
367 if(ptpf->m_argv != NULL)
368 {
369 for(i=0; i<ptpf->m_argv_len; i++)
370 {
371 if(ptpf->m_argv[i] != NULL)
372 {
373 free(ptpf->m_argv[i]);
374 ptpf->m_argv[i] = NULL;
375 }
376 }
377
378 free(ptpf->m_argv);
379 ptpf->m_argv = NULL;
380 }
381
382 return NULL;
383 }
384
385
386 // Open the temp file in the appropriate way...
387 //
388 if (!ptpf->m_mode) // If Read mode?
389 {
390 // we wish to spawn a command, intercept its output,
391 // and then get that output
392 //
393 if (!ptpf->m_argv[0])
394 {
395 fnTempPipeFileReleaseMemory(ptpf);
396
397 // Release additional memory
398 if(ptpf->m_argv != NULL)
399 {
400 for(i=0; i<ptpf->m_argv_len; i++)
401 {
402 if(ptpf->m_argv[i] != NULL)
403 {
404 free(ptpf->m_argv[i]);
405 ptpf->m_argv[i] = NULL;
406 }
407 }
408
409 free(ptpf->m_argv);
410 ptpf->m_argv = NULL;
411 }
412
413 return NULL;
414 }
415
416 if (ptpf->m_launchPerl)
417 fnPipeFileDoPerlLaunch(ptpf);
418 else
419 if (ptpf->m_doPerlGlob)
420 fnDoPerlGlob(ptpf->m_argv, ptpf->m_fileName); // hack to do perl globbing
421 else
422 spawnvp(P_WAIT, ptpf->m_argv[0], ptpf->m_argv);
423
424 ptpf->m_file = fopen (ptpf->m_fileName, (char *)"r"); // Get the Pipe file handle
425 }
426 else if (ptpf->m_mode) // If Write mode?
427 {
428 // we wish to open the file for writing now and
429 // do the command later
430 //
431 ptpf->m_file = fopen(ptpf->m_fileName, (char *)"w");
432 }
433
434 fnTempPipeFileReleaseMemory(ptpf);
435
436 // Release additional memory
437 if(ptpf->m_argv != NULL)
438 {
439 for(i=0; i<(ptpf->m_argv_len); i++)
440 {
441 if(ptpf->m_argv[i] != NULL)
442 {
443 free(ptpf->m_argv[i]);
444 ptpf->m_argv[i] = NULL;
445 }
446 }
447
448 free(ptpf->m_argv);
449 ptpf->m_argv = NULL;
450 }
451
452
453 return ptpf->m_file; // Return the Pipe file handle.
454}
455
456
457/*============================================================================================
458
459 Function : fnPipeFileClose
460
461 Description : This function closes the pipe file.
462
463 Parameters : ptpf (IN) - Input structure.
464
465 Returns : Nothing.
466
467==============================================================================================*/
468
469void fnPipeFileClose(PTEMPPIPEFILE ptpf)
470{
471 int i = 0;
472
473 if (ptpf->m_mode) // If Write mode?
474 {
475 // we wish to spawn a command using our temp file for
476 // its input
477 //
478 if(ptpf->m_file != NULL)
479 {
480 fclose (ptpf->m_file);
481 ptpf->m_file = NULL;
482 }
483
484 if (ptpf->m_launchPerl)
485 fnPipeFileDoPerlLaunch(ptpf);
486 else if (ptpf->m_argv)
487 spawnvp(P_WAIT, ptpf->m_argv[0], ptpf->m_argv);
488 }
489
490
491 // Close the temporary Pipe File, if opened
492 if (ptpf->m_file)
493 {
494 fclose(ptpf->m_file);
495 ptpf->m_file = NULL;
496 }
497 // Delete the temporary Pipe Filename if still valid and free the memory associated with the file name.
498 if(ptpf->m_fileName != NULL)
499 {
500// if (strlen(ptpf->m_fileName))
501 if (ptpf->m_fileName)
502 unlink(ptpf->m_fileName);
503
504 free(ptpf->m_fileName);
505 ptpf->m_fileName = NULL;
506 }
507
508/**
509 if(ptpf->m_argv != NULL)
510 {
511 for(i=0; i<(ptpf->m_argv_len); i++)
512 {
513 if(ptpf->m_argv[i] != NULL)
514 {
515 free(ptpf->m_argv[i]);
516 ptpf->m_argv[i] = NULL;
517 }
518 }
519
520 free(ptpf->m_argv);
521 ptpf->m_argv = NULL;
522 }
523**/
524
525 if (ptpf->m_perlSynchSemaphore)
526 {
527 #ifdef MPK_ON
528 kSemaphoreFree(ptpf->m_perlSynchSemaphore);
529 #else
530 CloseLocalSemaphore(ptpf->m_perlSynchSemaphore);
531 #endif //MPK_ON
532 }
533
534
535 return;
536}
537
538
539/*============================================================================================
540
541 Function : fnPipeFileDoPerlLaunch
542
543 Description : This function launches Perl.
544
545 Parameters : ptpf (IN) - Input structure.
546
547 Returns : Nothing.
548
549==============================================================================================*/
550
551void fnPipeFileDoPerlLaunch(PTEMPPIPEFILE ptpf)
552{
553 char curdir[_MAX_PATH] = {'\0'};
554 char* pcwd = NULL;
555
556 int i=0;
557
558
559 // save off the current working directory to restore later
560 // this is just a hack! these problems of synchronization and
561 // restoring calling context need a much better solution!
562 pcwd = (char *)getcwd(curdir, sizeof(curdir)-1);
563 fnSystemCommand(ptpf->m_argv, ptpf->m_argv_len);
564 if (ptpf->m_perlSynchSemaphore)
565 {
566 #ifdef MPK_ON
567 kSemaphoreWait(ptpf->m_perlSynchSemaphore);
568 #else
569 WaitOnLocalSemaphore(ptpf->m_perlSynchSemaphore);
570 #endif //MPK_ON
571 }
572
573 if (pcwd)
574 chdir(pcwd);
575
576 return;
577}
578
579
580/*============================================================================================
581
582 Function : fnTempPipeFile
583
584 Description : This function initialises the variables of the structure passed in.
585
586 Parameters : ptpf (IN) - Input structure.
587
588 Returns : Nothing.
589
590==============================================================================================*/
591
592void fnTempPipeFile(PTEMPPIPEFILE ptpf)
593{
594 ptpf->m_fileName = NULL;
595
596 ptpf->m_mode = FALSE; // Default mode = Read mode.
597 ptpf->m_file = NULL;
598 ptpf->m_pipeCommand = NULL;
599 ptpf->m_argv = NULL;
600
601 ptpf->m_redirect = NULL;
602
603 ptpf->m_launchPerl = FALSE;
604 ptpf->m_doPerlGlob = FALSE;
605
606 #ifdef MPK_ON
607 ptpf->m_perlSynchSemaphore = NULL;
608 #else
609 ptpf->m_perlSynchSemaphore = 0L;
610 #endif
611
612 ptpf->m_argv_len = 0;
613
614 return;
615}
616
617
618/*============================================================================================
619
620 Function : fnTempPipeFileReleaseMemory
621
622 Description : This function frees the memory allocated to various buffers.
623
624 Parameters : ptpf (IN) - Input structure.
625
626 Returns : Nothing.
627
628==============================================================================================*/
629
630void fnTempPipeFileReleaseMemory(PTEMPPIPEFILE ptpf)
631{
632 int i=0;
633
634
635 if (ptpf->m_pipeCommand)
636 {
637 if(ptpf->m_pipeCommand->m_argv != NULL)
638 {
639 for(i=0; i<ptpf->m_pipeCommand->m_argv_len; i++)
640 {
641 if(ptpf->m_pipeCommand->m_argv[i] != NULL)
642 {
643 free(ptpf->m_pipeCommand->m_argv[i]);
644 ptpf->m_pipeCommand->m_argv[i] = NULL;
645 }
646 }
647
648 free(ptpf->m_pipeCommand->m_argv);
649 ptpf->m_pipeCommand->m_argv = NULL;
650 }
651
652 if(ptpf->m_pipeCommand->sSkippedToken != NULL)
653 {
654 free(ptpf->m_pipeCommand->sSkippedToken);
655 ptpf->m_pipeCommand->sSkippedToken = NULL;
656 }
657/****
658// Commented since these are not being used. Still retained here.
659// To be removed once things are proved to be working fine to a good confident level,
660
661 if(ptpf->m_pipeCommand->nextarg)
662 {
663 free(ptpf->m_pipeCommand->nextarg);
664 ptpf->m_pipeCommand->nextarg = NULL;
665 }
666
667 if(ptpf->m_pipeCommand->m_redirInName)
668 {
669 free(ptpf->m_pipeCommand->m_redirInName);
670 ptpf->m_pipeCommand->m_redirInName = NULL;
671 }
672 if(ptpf->m_pipeCommand->m_redirOutName)
673 {
674 free(ptpf->m_pipeCommand->m_redirOutName);
675 ptpf->m_pipeCommand->m_redirOutName = NULL;
676 }
677 if(ptpf->m_pipeCommand->m_redirErrName)
678 {
679 free(ptpf->m_pipeCommand->m_redirErrName);
680 ptpf->m_pipeCommand->m_redirErrName = NULL;
681 }
682 if(ptpf->m_pipeCommand->m_redirBothName)
683 {
684 free(ptpf->m_pipeCommand->m_redirBothName);
685 ptpf->m_pipeCommand->m_redirBothName = NULL;
686 }
687****/
688
689 if(ptpf->m_pipeCommand != NULL)
690 {
691 free(ptpf->m_pipeCommand);
692 ptpf->m_pipeCommand = NULL;
693 }
694 }
695
696 if(ptpf->m_redirect != NULL)
697 {
698 free(ptpf->m_redirect);
699 ptpf->m_redirect = NULL;
700 }
701
702 return;
703}
704