1 /* $OpenBSD: terminal.c,v 1.14 2017/01/21 08:22:57 krw Exp $ */
2 /* $NetBSD: terminal.c,v 1.2 1997/10/10 16:34:05 lukem Exp $ */
3 /*
4 * Copyright (c) 1983-2003, Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * + Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * + Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * + Neither the name of the University of California, San Francisco nor
17 * the names of its contributors may be used to endorse or promote
18 * products derived from this software without specific prior written
19 * permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/select.h>
35 #include <err.h>
36 #include <stdarg.h>
37 #include <syslog.h>
38 #include <string.h>
39
40 #include "conf.h"
41 #include "hunt.h"
42 #include "server.h"
43
44 #define TERM_WIDTH 80 /* Assume terminals are 80-char wide */
45
46 /*
47 * cgoto:
48 * Move the cursor to the given position on the given player's
49 * terminal.
50 */
51 void
cgoto(PLAYER * pp,int y,int x)52 cgoto(PLAYER *pp, int y, int x)
53 {
54
55 if (pp == ALL_PLAYERS) {
56 for (pp = Player; pp < End_player; pp++)
57 cgoto(pp, y, x);
58 for (pp = Monitor; pp < End_monitor; pp++)
59 cgoto(pp, y, x);
60 return;
61 }
62
63 if (x == pp->p_curx && y == pp->p_cury)
64 return;
65
66 sendcom(pp, MOVE, y, x);
67 pp->p_cury = y;
68 pp->p_curx = x;
69 }
70
71 /*
72 * outch:
73 * Put out a single character.
74 */
75 void
outch(PLAYER * pp,char ch)76 outch(PLAYER *pp, char ch)
77 {
78
79 if (pp == ALL_PLAYERS) {
80 for (pp = Player; pp < End_player; pp++)
81 outch(pp, ch);
82 for (pp = Monitor; pp < End_monitor; pp++)
83 outch(pp, ch);
84 return;
85 }
86
87 if (++pp->p_curx >= TERM_WIDTH) {
88 pp->p_curx = 0;
89 pp->p_cury++;
90 }
91 (void) putc(ch, pp->p_output);
92 }
93
94 /*
95 * outstr:
96 * Put out a string of the given length.
97 */
98 void
outstr(PLAYER * pp,char * str,int len)99 outstr(PLAYER *pp, char *str, int len)
100 {
101 if (pp == ALL_PLAYERS) {
102 for (pp = Player; pp < End_player; pp++)
103 outstr(pp, str, len);
104 for (pp = Monitor; pp < End_monitor; pp++)
105 outstr(pp, str, len);
106 return;
107 }
108
109 pp->p_curx += len;
110 pp->p_cury += (pp->p_curx / TERM_WIDTH);
111 pp->p_curx %= TERM_WIDTH;
112 while (len--)
113 (void) putc(*str++, pp->p_output);
114 }
115
116 /*
117 * outat:
118 * draw a string at a location on the client.
119 * Cursor doesn't move if the location is invalid
120 */
121 void
outyx(PLAYER * pp,int y,int x,const char * fmt,...)122 outyx(PLAYER *pp, int y, int x, const char *fmt, ...)
123 {
124 va_list ap;
125 char buf[BUFSIZ];
126 int len;
127
128 va_start(ap, fmt);
129 len = vsnprintf(buf, sizeof(buf), fmt, ap);
130 va_end(ap);
131 if (len == -1)
132 len = 0;
133 if (len >= (int)sizeof(buf))
134 len = sizeof(buf) - 1;
135 if (y >= 0 && x >= 0)
136 cgoto(pp, y, x);
137 if (len > 0)
138 outstr(pp, buf, len);
139 }
140
141 /*
142 * clrscr:
143 * Clear the screen, and reset the current position on the screen.
144 */
145 void
clrscr(PLAYER * pp)146 clrscr(PLAYER *pp)
147 {
148
149 if (pp == ALL_PLAYERS) {
150 for (pp = Player; pp < End_player; pp++)
151 clrscr(pp);
152 for (pp = Monitor; pp < End_monitor; pp++)
153 clrscr(pp);
154 return;
155 }
156
157 sendcom(pp, CLEAR);
158 pp->p_cury = 0;
159 pp->p_curx = 0;
160 }
161
162 /*
163 * ce:
164 * Clear to the end of the line
165 */
166 void
ce(PLAYER * pp)167 ce(PLAYER *pp)
168 {
169 sendcom(pp, CLRTOEOL);
170 }
171
172 /*
173 * sendcom:
174 * Send a command to the given user
175 */
176 void
sendcom(PLAYER * pp,int command,...)177 sendcom(PLAYER *pp, int command, ...)
178 {
179 va_list ap;
180 char buf[3];
181 int len = 0;
182
183 va_start(ap, command);
184 buf[len++] = command;
185 switch (command & 0377) {
186 case MOVE:
187 buf[len++] = va_arg(ap, int);
188 buf[len++] = va_arg(ap, int);
189 break;
190 case ADDCH:
191 case READY:
192 case ENDWIN:
193 buf[len++] = va_arg(ap, int);
194 break;
195 }
196 va_end(ap);
197
198 if (pp == ALL_PLAYERS) {
199 for (pp = Player; pp < End_player; pp++)
200 fwrite(buf, sizeof buf[0], len, pp->p_output);
201 for (pp = Monitor; pp < End_monitor; pp++)
202 fwrite(buf, sizeof buf[0], len, pp->p_output);
203 return;
204 } else
205 fwrite(buf, sizeof buf[0], len, pp->p_output);
206 }
207
208 /*
209 * sync:
210 * Flush the output buffer to the player
211 */
212 void
flush(PLAYER * pp)213 flush(PLAYER *pp)
214 {
215 if (pp == ALL_PLAYERS) {
216 for (pp = Player; pp < End_player; pp++)
217 fflush(pp->p_output);
218 for (pp = Monitor; pp < End_monitor; pp++)
219 fflush(pp->p_output);
220 } else
221 fflush(pp->p_output);
222 }
223
224 void
logx(int prio,const char * fmt,...)225 logx(int prio, const char *fmt, ...)
226 {
227 va_list ap;
228
229 va_start(ap, fmt);
230 if (conf_syslog)
231 vsyslog(prio, fmt, ap);
232 else if (conf_logerr)
233 /* if (prio < LOG_NOTICE) */
234 vwarnx(fmt, ap);
235 va_end(ap);
236 }
237
238 void
logit(int prio,const char * fmt,...)239 logit(int prio, const char *fmt, ...)
240 {
241 va_list ap;
242 char fmtm[1024];
243
244 va_start(ap, fmt);
245 if (conf_syslog) {
246 strlcpy(fmtm, fmt, sizeof fmtm);
247 strlcat(fmtm, ": %m", sizeof fmtm);
248 vsyslog(prio, fmtm, ap);
249 } else if (conf_logerr)
250 /* if (prio < LOG_NOTICE) */
251 vwarn(fmt, ap);
252 va_end(ap);
253 }
254