3 * Copyright © 2001 Novell, Inc. All Rights Reserved.
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.
12 * DESCRIPTION : Functions to implement pipes on NetWare.
14 * Date : January 2001.
28 // This was added since the compile failed saying "undefined P_WAIT"
29 // when USE_ITHREADS was commented in the makefile
41 /*============================================================================================
43 Function : fnPipeFileMakeArgv
45 Description : This function makes the argument array.
47 Parameters : ptpf (IN) - Input structure.
51 ==============================================================================================*/
53 BOOL fnPipeFileMakeArgv(PTEMPPIPEFILE ptpf)
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)
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++)
75 ptpf->m_argv[i] = (char *) malloc(MAX_DN_BYTES * sizeof(char));
76 if (ptpf->m_argv[i] == NULL)
82 free(ptpf->m_argv[j]);
83 ptpf->m_argv[j] = NULL;
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)
97 strcpy(ptpf->m_argv[dindex], ptpf->m_pipeCommand->m_argv[sindex]);
102 if (stricmp(ptpf->m_argv[0], PERL_COMMAND_NAME) == 0) // If Perl is the first command.
104 ptpf->m_launchPerl = TRUE;
107 ptpf->m_perlSynchSemaphore = kSemaphoreAlloc((BYTE *)"pipeSemaphore", 0);
109 ptpf->m_perlSynchSemaphore = OpenLocalSemaphore(0);
112 else if (stricmp(ptpf->m_argv[0], (char *)"perlglob") == 0)
113 ptpf->m_doPerlGlob = TRUE;
116 // Create last argument, which will redirect to or from the temp file
117 if (!ptpf->m_doPerlGlob || ptpf->m_mode)
119 if (!ptpf->m_mode) // If read mode?
121 if (ptpf->m_launchPerl)
122 strcpy(ptpf->m_redirect, (char *)">");
124 strcpy(ptpf->m_redirect, (char *)"(CLIB_OPT)/>");
128 if (ptpf->m_launchPerl)
129 strcpy(ptpf->m_redirect, (char *)"<");
131 strcpy(ptpf->m_redirect, (char *)"(CLIB_OPT)/<");
133 strcat(ptpf->m_redirect, ptpf->m_fileName);
135 if (ptpf->m_launchPerl)
137 char tbuf[15] = {'\0'};
138 sprintf(tbuf, (char *)" -{%x", ptpf->m_perlSynchSemaphore);
139 strcat(ptpf->m_redirect, tbuf);
142 strcpy(ptpf->m_argv[dindex], (char*) ptpf->m_redirect);
146 if (dindex < (ptpf->m_pipeCommand->m_argc + 1))
148 if(ptpf->m_argv[dindex])
150 free(ptpf->m_argv[dindex]);
151 ptpf->m_argv[dindex] = NULL; // NULL termination - required for spawnvp call.
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.
163 /*============================================================================================
165 Function : fnPipeFileOpen
167 Description : This function opens the pipe file.
169 Parameters : ptpf (IN) - Input structure.
170 command (IN) - Input command string.
171 mode (IN) - Mode of opening.
173 Returns : File pointer.
175 ==============================================================================================*/
177 FILE* fnPipeFileOpen(PTEMPPIPEFILE ptpf, char* command, char* mode)
181 char tempName[_MAX_PATH] = {'\0'};
184 ptpf->m_fileName = (char *) malloc(_MAX_PATH * sizeof(char));
185 if(ptpf->m_fileName == NULL)
188 // The char array is emptied so that there is no junk characters.
189 strncpy(ptpf->m_fileName, "", (_MAX_PATH * sizeof(char)));
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
200 if(ptpf->m_fileName != NULL)
202 // if (strlen(ptpf->m_fileName))
203 if (ptpf->m_fileName)
204 unlink(ptpf->m_fileName);
206 free(ptpf->m_fileName);
207 ptpf->m_fileName = NULL;
214 ptpf->m_pipeCommand = (PCOMMANDLINEPARSER) malloc(sizeof(COMMANDLINEPARSER));
215 if (!ptpf->m_pipeCommand)
217 // if (strlen(ptpf->m_fileName))
218 if (ptpf->m_fileName)
219 unlink(ptpf->m_fileName);
221 free(ptpf->m_fileName);
222 ptpf->m_fileName = NULL;
227 // Initialise the variables
228 ptpf->m_pipeCommand->m_isValid = TRUE;
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,
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;
241 ptpf->m_pipeCommand->sSkippedToken = NULL;
242 ptpf->m_pipeCommand->m_argv = NULL;
243 ptpf->m_pipeCommand->new_argv = NULL;
246 ptpf->m_pipeCommand->m_qSemaphore = NULL;
248 ptpf->m_pipeCommand->m_qSemaphore = 0L;
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;
257 ptpf->m_pipeCommand->m_argv = (char **) malloc(ptpf->m_pipeCommand->m_argv_len * sizeof(char *));
258 if (ptpf->m_pipeCommand->m_argv == NULL)
260 free(ptpf->m_pipeCommand);
261 ptpf->m_pipeCommand = NULL;
263 // if (strlen(ptpf->m_fileName))
264 if (ptpf->m_fileName)
265 unlink(ptpf->m_fileName);
267 free(ptpf->m_fileName);
268 ptpf->m_fileName = NULL;
272 ptpf->m_pipeCommand->m_argv[0] = (char *) malloc(MAX_DN_BYTES * sizeof(char));
273 if (ptpf->m_pipeCommand->m_argv[0] == NULL)
277 if(ptpf->m_pipeCommand->m_argv[j])
279 free(ptpf->m_pipeCommand->m_argv[j]);
280 ptpf->m_pipeCommand->m_argv[j]=NULL;
283 free(ptpf->m_pipeCommand->m_argv);
284 ptpf->m_pipeCommand->m_argv=NULL;
286 free(ptpf->m_pipeCommand);
287 ptpf->m_pipeCommand = NULL;
289 // if (strlen(ptpf->m_fileName))
290 if (ptpf->m_fileName)
291 unlink(ptpf->m_fileName);
293 free(ptpf->m_fileName);
294 ptpf->m_fileName = NULL;
300 ptpf->m_redirect = (char *) malloc(MAX_DN_BYTES * sizeof(char));
301 if (ptpf->m_redirect == NULL)
303 for(i=0; i<ptpf->m_pipeCommand->m_argv_len; i++)
305 if(ptpf->m_pipeCommand->m_argv[i] != NULL)
307 free(ptpf->m_pipeCommand->m_argv[i]);
308 ptpf->m_pipeCommand->m_argv[i] = NULL;
312 free(ptpf->m_pipeCommand->m_argv);
313 ptpf->m_pipeCommand->m_argv = NULL;
315 free(ptpf->m_pipeCommand);
316 ptpf->m_pipeCommand = NULL;
319 // if (strlen(ptpf->m_fileName))
320 if (ptpf->m_fileName)
321 unlink(ptpf->m_fileName);
323 free(ptpf->m_fileName);
324 ptpf->m_fileName = NULL;
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)));
336 // Parse the parameters.
337 fnCommandLineParser(ptpf->m_pipeCommand, (char *)command, TRUE);
338 if (!ptpf->m_pipeCommand->m_isValid)
340 fnTempPipeFileReleaseMemory(ptpf);
345 // Create a temporary file name
347 strncpy ( tempName, fnNwGetEnvironmentStr((char *)"TEMP", NWDEFPERLTEMP), (_MAX_PATH - 20) );
348 tempName[_MAX_PATH-20] = '\0';
349 strcat(tempName, (char *)"\\plXXXXXX.tmp");
350 if (!fnMy_MkTemp(tempName))
352 fnTempPipeFileReleaseMemory(ptpf);
356 // create a temporary place-holder file
357 fclose(fopen(tempName, (char *)"w"));
358 strcpy(ptpf->m_fileName, tempName);
361 // Make the argument array
362 if(!fnPipeFileMakeArgv(ptpf))
364 fnTempPipeFileReleaseMemory(ptpf);
366 // Release additional memory
367 if(ptpf->m_argv != NULL)
369 for(i=0; i<ptpf->m_argv_len; i++)
371 if(ptpf->m_argv[i] != NULL)
373 free(ptpf->m_argv[i]);
374 ptpf->m_argv[i] = NULL;
386 // Open the temp file in the appropriate way...
388 if (!ptpf->m_mode) // If Read mode?
390 // we wish to spawn a command, intercept its output,
391 // and then get that output
393 if (!ptpf->m_argv[0])
395 fnTempPipeFileReleaseMemory(ptpf);
397 // Release additional memory
398 if(ptpf->m_argv != NULL)
400 for(i=0; i<ptpf->m_argv_len; i++)
402 if(ptpf->m_argv[i] != NULL)
404 free(ptpf->m_argv[i]);
405 ptpf->m_argv[i] = NULL;
416 if (ptpf->m_launchPerl)
417 fnPipeFileDoPerlLaunch(ptpf);
419 if (ptpf->m_doPerlGlob)
420 fnDoPerlGlob(ptpf->m_argv, ptpf->m_fileName); // hack to do perl globbing
422 spawnvp(P_WAIT, ptpf->m_argv[0], ptpf->m_argv);
424 ptpf->m_file = fopen (ptpf->m_fileName, (char *)"r"); // Get the Pipe file handle
426 else if (ptpf->m_mode) // If Write mode?
428 // we wish to open the file for writing now and
429 // do the command later
431 ptpf->m_file = fopen(ptpf->m_fileName, (char *)"w");
434 fnTempPipeFileReleaseMemory(ptpf);
436 // Release additional memory
437 if(ptpf->m_argv != NULL)
439 for(i=0; i<(ptpf->m_argv_len); i++)
441 if(ptpf->m_argv[i] != NULL)
443 free(ptpf->m_argv[i]);
444 ptpf->m_argv[i] = NULL;
453 return ptpf->m_file; // Return the Pipe file handle.
457 /*============================================================================================
459 Function : fnPipeFileClose
461 Description : This function closes the pipe file.
463 Parameters : ptpf (IN) - Input structure.
467 ==============================================================================================*/
469 void fnPipeFileClose(PTEMPPIPEFILE ptpf)
473 if (ptpf->m_mode) // If Write mode?
475 // we wish to spawn a command using our temp file for
478 if(ptpf->m_file != NULL)
480 fclose (ptpf->m_file);
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);
491 // Close the temporary Pipe File, if opened
494 fclose(ptpf->m_file);
497 // Delete the temporary Pipe Filename if still valid and free the memory associated with the file name.
498 if(ptpf->m_fileName != NULL)
500 // if (strlen(ptpf->m_fileName))
501 if (ptpf->m_fileName)
502 unlink(ptpf->m_fileName);
504 free(ptpf->m_fileName);
505 ptpf->m_fileName = NULL;
509 if(ptpf->m_argv != NULL)
511 for(i=0; i<(ptpf->m_argv_len); i++)
513 if(ptpf->m_argv[i] != NULL)
515 free(ptpf->m_argv[i]);
516 ptpf->m_argv[i] = NULL;
525 if (ptpf->m_perlSynchSemaphore)
528 kSemaphoreFree(ptpf->m_perlSynchSemaphore);
530 CloseLocalSemaphore(ptpf->m_perlSynchSemaphore);
539 /*============================================================================================
541 Function : fnPipeFileDoPerlLaunch
543 Description : This function launches Perl.
545 Parameters : ptpf (IN) - Input structure.
549 ==============================================================================================*/
551 void fnPipeFileDoPerlLaunch(PTEMPPIPEFILE ptpf)
553 char curdir[_MAX_PATH] = {'\0'};
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)
567 kSemaphoreWait(ptpf->m_perlSynchSemaphore);
569 WaitOnLocalSemaphore(ptpf->m_perlSynchSemaphore);
580 /*============================================================================================
582 Function : fnTempPipeFile
584 Description : This function initialises the variables of the structure passed in.
586 Parameters : ptpf (IN) - Input structure.
590 ==============================================================================================*/
592 void fnTempPipeFile(PTEMPPIPEFILE ptpf)
594 ptpf->m_fileName = NULL;
596 ptpf->m_mode = FALSE; // Default mode = Read mode.
598 ptpf->m_pipeCommand = NULL;
601 ptpf->m_redirect = NULL;
603 ptpf->m_launchPerl = FALSE;
604 ptpf->m_doPerlGlob = FALSE;
607 ptpf->m_perlSynchSemaphore = NULL;
609 ptpf->m_perlSynchSemaphore = 0L;
612 ptpf->m_argv_len = 0;
618 /*============================================================================================
620 Function : fnTempPipeFileReleaseMemory
622 Description : This function frees the memory allocated to various buffers.
624 Parameters : ptpf (IN) - Input structure.
628 ==============================================================================================*/
630 void fnTempPipeFileReleaseMemory(PTEMPPIPEFILE ptpf)
635 if (ptpf->m_pipeCommand)
637 if(ptpf->m_pipeCommand->m_argv != NULL)
639 for(i=0; i<ptpf->m_pipeCommand->m_argv_len; i++)
641 if(ptpf->m_pipeCommand->m_argv[i] != NULL)
643 free(ptpf->m_pipeCommand->m_argv[i]);
644 ptpf->m_pipeCommand->m_argv[i] = NULL;
648 free(ptpf->m_pipeCommand->m_argv);
649 ptpf->m_pipeCommand->m_argv = NULL;
652 if(ptpf->m_pipeCommand->sSkippedToken != NULL)
654 free(ptpf->m_pipeCommand->sSkippedToken);
655 ptpf->m_pipeCommand->sSkippedToken = NULL;
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,
661 if(ptpf->m_pipeCommand->nextarg)
663 free(ptpf->m_pipeCommand->nextarg);
664 ptpf->m_pipeCommand->nextarg = NULL;
667 if(ptpf->m_pipeCommand->m_redirInName)
669 free(ptpf->m_pipeCommand->m_redirInName);
670 ptpf->m_pipeCommand->m_redirInName = NULL;
672 if(ptpf->m_pipeCommand->m_redirOutName)
674 free(ptpf->m_pipeCommand->m_redirOutName);
675 ptpf->m_pipeCommand->m_redirOutName = NULL;
677 if(ptpf->m_pipeCommand->m_redirErrName)
679 free(ptpf->m_pipeCommand->m_redirErrName);
680 ptpf->m_pipeCommand->m_redirErrName = NULL;
682 if(ptpf->m_pipeCommand->m_redirBothName)
684 free(ptpf->m_pipeCommand->m_redirBothName);
685 ptpf->m_pipeCommand->m_redirBothName = NULL;
689 if(ptpf->m_pipeCommand != NULL)
691 free(ptpf->m_pipeCommand);
692 ptpf->m_pipeCommand = NULL;
696 if(ptpf->m_redirect != NULL)
698 free(ptpf->m_redirect);
699 ptpf->m_redirect = NULL;