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;
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);
115 if (robotProcess > 0)
116 RobotCmd(1, "Exit\n");
121 static MyEventType RobotGenFunc(EventGenRec *gen, MyEvent *event)
129 robotGen.ready = more;
132 if (robotBufMsg > 0) {
134 * Grrrrrr! SunOS 4.1 doesn't have memmove (or atexit)
135 * I'm told some others have a broken memmove
137 * memmove(robotBuf, robotBuf + robotBufMsg,
138 * robotBufSize - robotBufMsg);
140 for (i = robotBufMsg; i < robotBufSize; ++i)
141 robotBuf[i - robotBufMsg] = robotBuf[i];
143 robotBufSize -= robotBufMsg;
150 result = read(fromRobotFd, robotBuf + robotBufSize,
151 sizeof(robotBuf) - robotBufSize);
152 } while (result < 0 && errno == EINTR);
155 robotBufSize += result;
157 if (!(p = memchr(robotBuf, '\n', robotBufSize))) {
158 if (robotBufSize >= sizeof(robotBuf))
159 fatal("Line from robot is too long");
163 robotBufMsg = p - robotBuf + 1;
164 robotGen.ready = more = (memchr(robotBuf + robotBufMsg, '\n',
165 robotBufSize - robotBufMsg) != NULL);
166 event->u.robot.size = p - robotBuf;
167 event->u.robot.data = robotBuf;