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