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);
33 static EventGenRec robotGen =
34 { NULL, 0, FT_read, -1, RobotGenFunc, EM_robot };
36 static int robotProcess;
38 static int toRobotFd, fromRobotFd;
40 static char robotBuf[128];
41 static int robotBufSize, robotBufMsg;
43 static int gotSigPipe;
45 ExtFunc void InitRobot(char *robotProg)
51 signal(SIGPIPE, CatchPipe);
53 if (pipe(to) || pipe(from))
55 robotProcess = fork();
58 if (robotProcess == 0) {
59 dup2(to[0], STDIN_FILENO);
60 dup2(from[1], STDOUT_FILENO);
65 execl("/bin/sh", "sh", "-c", robotProg, NULL);
71 robotGen.fd = fromRobotFd = from[0];
72 if (!(toRobot = fdopen(toRobotFd, "w")))
74 if ((status = fcntl(fromRobotFd, F_GETFL, 0)) < 0)
77 if (fcntl(fromRobotFd, F_SETFL, status) < 0)
79 AddEventGen(&robotGen);
80 RobotCmd(1, "Version %d\n", ROBOT_VERSION);
81 if (WaitMyEvent(&event, EM_robot) != E_robot)
82 fatal("Robot didn't start successfully");
83 if (1 > sscanf(event.u.robot.data, "Version %d", &robotVersion)
85 fatal("Invalid Version line from robot");
86 if (robotVersion > ROBOT_VERSION)
87 robotVersion = ROBOT_VERSION;
90 ExtFunc void CatchPipe(int sig)
92 robotGen.ready = gotSigPipe = 1;
95 ExtFunc void RobotCmd(int flush, char *fmt, ...)
100 vfprintf(toRobot, fmt, args);
106 ExtFunc void RobotTimeStamp(void)
108 RobotCmd(1, "TimeStamp %.3f\n", CurTimeval() / 1.0e6);
111 ExtFunc void CloseRobot(void)
113 RemoveEventGen(&robotGen);
114 if (robotProcess > 0)
115 RobotCmd(1, "Exit\n");
120 static MyEventType RobotGenFunc(EventGenRec *gen, MyEvent *event)
128 robotGen.ready = more;
131 if (robotBufMsg > 0) {
133 * Grrrrrr! SunOS 4.1 doesn't have memmove (or atexit)
134 * I'm told some others have a broken memmove
136 * memmove(robotBuf, robotBuf + robotBufMsg,
137 * robotBufSize - robotBufMsg);
139 for (i = robotBufMsg; i < robotBufSize; ++i)
140 robotBuf[i - robotBufMsg] = robotBuf[i];
142 robotBufSize -= robotBufMsg;
149 result = read(fromRobotFd, robotBuf + robotBufSize,
150 sizeof(robotBuf) - robotBufSize);
151 } while (result < 0 && errno == EINTR);
154 robotBufSize += result;
156 if (!(p = memchr(robotBuf, '\n', robotBufSize))) {
157 if (robotBufSize >= sizeof(robotBuf))
158 fatal("Line from robot is too long");
162 robotBufMsg = p - robotBuf + 1;
163 robotGen.ready = more = (memchr(robotBuf + robotBufMsg, '\n',
164 robotBufSize - robotBufMsg) != NULL);
165 event->u.robot.size = p - robotBuf;
166 event->u.robot.data = robotBuf;