/*
* C4 -- CVS like front end to the Perforce p4 SCM tool.
*
* Copyright (c) 1997, Neil Russell. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Neil Russell.
* 4. The name Neil Russell may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY NEIL RUSSELL ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NEIL RUSSELL BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Command execution.
*/
#include "defs.h"
/**************************************************/
/*
* Command invocation.
*/
int CmdArgs; /* Number of args seen */
int CmdExec = 1; /* '-n' ommand line option */
char * CmdP4 = "p4"; /* Name of the real p4 command */
static char * cmd; /* Command string under construction */
static int cmd_index; /* Next available argument */
static int cmd_base; /* First argument of xargs list */
static int cmd_size; /* Available argument space */
static int cmd_clobber; /* Command changes things */
static void (*cmd_func)(char *); /* Output processing function */
void
Command(char * c, void (*f)(char *), int clobber)
{
/*
* Calculate the size of the argument space.
*/
if (!cmd)
{
char ** ep;
extern char ** environ;
cmd_size = NCARGS - 4 * 1024;
for (ep = environ; *ep; ep++)
cmd_size -= strlen(*ep) + 1 + sizeof (*ep);
if (cmd_size > 32768)
cmd_size = 32768;
cmd = Alloc(cmd_size);
}
/*
* Copy the initial command string into the arg string (we
* assume that the command string will fit in the available
* argument space).
*/
strcpy(cmd, CmdP4);
strcat(cmd, " ");
strcat(cmd, c);
cmd_index = strlen(cmd);
cmd_base = cmd_index;
cmd_func = f;
cmd_clobber = clobber;
CmdArgs = 0;
}
void
CommandDone(void)
{
FILE * fd;
char line[1024];
if (Debug >= 1)
printf("\t%s\n", cmd);
if (cmd_clobber && !CmdExec)
return;
if (!cmd_func)
system(cmd);
else
{
fd = popen(cmd, "r");
if (!fd)
{
cmd[cmd_base] = '\0';
Error(1, "Can't popen command (%.40s)", cmd);
}
while (fgets(line, sizeof line, fd))
{
char * nl;
if (nl = strchr(line, '\n'))
*nl = '\0';
(*cmd_func)(line);
}
pclose(fd);
}
}
void
CommandArg(char * a)
{
int l;
l = strlen(a);
if (cmd_index + 1 + l + 1 > cmd_size)
{
CommandDone();
cmd_index = cmd_base;
}
strcpy(&cmd[cmd_index++], " ");
strcpy(&cmd[cmd_index], a);
cmd_index += l;
CmdArgs++;
}