2 * Netris -- A free networked version of T*tris
3 * Copyright (C) 1994,1995,1996 Mark H. Weaver <mhw@netris.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * $Id: robot.c,v 1.8 1996/02/09 08:22:15 mhw Exp $
28 #include <sys/types.h>
32 static MyEventType RobotGenFunc(EventGenRec *gen, MyEvent *event);
34 static EventGenRec robotGen =
35 { NULL, 0, FT_read, -1, RobotGenFunc, EM_robot };
37 static int robotProcess;
38 static FILE *toRobot = NULL;
39 static int toRobotFd, fromRobotFd;
41 static char robotBuf[128];
42 static int robotBufSize, robotBufMsg;
44 static int gotSigPipe;
46 ExtFunc void InitRobot(char *robotProg)
52 signal(SIGPIPE, CatchPipe);
54 if (pipe(to) || pipe(from))
56 robotProcess = fork();
59 if (robotProcess == 0) {
60 dup2(to[0], STDIN_FILENO);
61 dup2(from[1], STDOUT_FILENO);
66 execl("/bin/sh", "sh", "-c", robotProg, NULL);
72 robotGen.fd = fromRobotFd = from[0];
73 if (!(toRobot = fdopen(toRobotFd, "w")))
75 if ((status = fcntl(fromRobotFd, F_GETFL, 0)) < 0)
78 if (fcntl(fromRobotFd, F_SETFL, status) < 0)
80 AddEventGen(&robotGen);
81 RobotCmd(1, "Version %d\n", ROBOT_VERSION);
82 if (WaitMyEvent(&event, EM_robot) != E_robot)
83 fatal("Robot didn't start successfully");
84 if (1 > sscanf(event.u.robot.data, "Version %d", &robotVersion)
86 fatal("Invalid Version line from robot");
87 if (robotVersion > ROBOT_VERSION)
88 robotVersion = ROBOT_VERSION;
91 ExtFunc void CatchPipe(int sig)
93 robotGen.ready = gotSigPipe = 1;
96 ExtFunc void RobotCmd(int flush, char *fmt, ...)
101 vfprintf(toRobot, fmt, args);
107 ExtFunc void RobotTimeStamp(void)
109 RobotCmd(1, "TimeStamp %.3f\n", CurTimeval() / 1.0e6);
112 ExtFunc void CloseRobot(void)
114 RemoveEventGen(&robotGen);
116 if (robotProcess > 0)
117 RobotCmd(1, "Exit\n");
124 static MyEventType RobotGenFunc(EventGenRec *gen, MyEvent *event)
132 robotGen.ready = more;
135 if (robotBufMsg > 0) {
137 * Grrrrrr! SunOS 4.1 doesn't have memmove (or atexit)
138 * I'm told some others have a broken memmove
140 * memmove(robotBuf, robotBuf + robotBufMsg,
141 * robotBufSize - robotBufMsg);
143 for (i = robotBufMsg; i < robotBufSize; ++i)
144 robotBuf[i - robotBufMsg] = robotBuf[i];
146 robotBufSize -= robotBufMsg;
153 result = read(fromRobotFd, robotBuf + robotBufSize,
154 sizeof(robotBuf) - robotBufSize);
155 } while (result < 0 && errno == EINTR);
158 robotBufSize += result;
160 if (!(p = memchr(robotBuf, '\n', robotBufSize))) {
161 if (robotBufSize >= sizeof(robotBuf))
162 fatal("Line from robot is too long");
166 robotBufMsg = p - robotBuf + 1;
167 robotGen.ready = more = (memchr(robotBuf + robotBufMsg, '\n',
168 robotBufSize - robotBufMsg) != NULL);
169 event->u.robot.size = p - robotBuf;
170 event->u.robot.data = robotBuf;