12089Ssos/*-
2330449Seadler * SPDX-License-Identifier: BSD-3-Clause
3330449Seadler *
4228976Suqs * Copyright (c) 1994 S��ren Schmidt
52089Ssos * All rights reserved.
62089Ssos *
72089Ssos * Redistribution and use in source and binary forms, with or without
82089Ssos * modification, are permitted provided that the following conditions
92089Ssos * are met:
102089Ssos * 1. Redistributions of source code must retain the above copyright
115994Ssos *    notice, this list of conditions and the following disclaimer,
125994Ssos *    in this position and unchanged.
132089Ssos * 2. Redistributions in binary form must reproduce the above copyright
142089Ssos *    notice, this list of conditions and the following disclaimer in the
152089Ssos *    documentation and/or other materials provided with the distribution.
162089Ssos * 3. The name of the author may not be used to endorse or promote products
1797748Sschweikh *    derived from this software without specific prior written permission
182089Ssos *
192089Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
202089Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
212089Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
222089Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
232089Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
242089Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
252089Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
262089Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
272089Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
282089Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
292089Ssos */
302089Ssos
3130764Scharnier#ifndef lint
3230764Scharnierstatic const char rcsid[] =
3350479Speter  "$FreeBSD: stable/11/usr.sbin/vidcontrol/decode.c 330449 2018-03-05 07:26:05Z eadler $";
3430764Scharnier#endif /* not lint */
3530764Scharnier
362089Ssos#include <stdio.h>
3723457Sbrian#include <string.h>
3823457Sbrian#include "decode.h"
392089Ssos
4075344Ssobomaxint decode(FILE *fd, char *buffer, int len)
412089Ssos{
4275344Ssobomax	int n, pos = 0, tpos;
4375344Ssobomax	char *bp, *p;
4475344Ssobomax	char tbuffer[3];
452089Ssos	char temp[128];
462089Ssos
472089Ssos#define	DEC(c)	(((c) - ' ') & 0x3f)
482089Ssos
492089Ssos	do {
508857Srgrimes		if (!fgets(temp, sizeof(temp), fd))
512089Ssos			return(0);
522089Ssos	} while (strncmp(temp, "begin ", 6));
53140159Sdelphij	sscanf(temp, "begin %o %s", (unsigned *)&n, temp);
5475344Ssobomax	bp = buffer;
552089Ssos	for (;;) {
562089Ssos		if (!fgets(p = temp, sizeof(temp), fd))
572089Ssos			return(0);
582089Ssos		if ((n = DEC(*p)) <= 0)
592089Ssos			break;
6075344Ssobomax		for (++p; n > 0; p += 4, n -= 3) {
6175344Ssobomax			tpos = 0;
622089Ssos			if (n >= 3) {
6375344Ssobomax				tbuffer[tpos++] = DEC(p[0])<<2 | DEC(p[1])>>4;
6475344Ssobomax				tbuffer[tpos++] = DEC(p[1])<<4 | DEC(p[2])>>2;
6575344Ssobomax				tbuffer[tpos++] = DEC(p[2])<<6 | DEC(p[3]);
662089Ssos			}
672089Ssos			else {
682089Ssos				if (n >= 1) {
6975344Ssobomax					tbuffer[tpos++] =
702089Ssos						DEC(p[0])<<2 | DEC(p[1])>>4;
712089Ssos				}
722089Ssos				if (n >= 2) {
7375344Ssobomax					tbuffer[tpos++] =
742089Ssos						DEC(p[1])<<4 | DEC(p[2])>>2;
752089Ssos				}
762089Ssos				if (n >= 3) {
7775344Ssobomax					tbuffer[tpos++] =
782089Ssos						DEC(p[2])<<6 | DEC(p[3]);
792089Ssos				}
802089Ssos			}
8175344Ssobomax			if (tpos == 0)
8275344Ssobomax				continue;
8375344Ssobomax			if (tpos + pos > len) {
8475344Ssobomax				tpos = len - pos;
8575344Ssobomax				/*
8675344Ssobomax				 * Arrange return value > len to indicate
8775344Ssobomax				 * overflow.
8875344Ssobomax				 */
8975344Ssobomax				pos++;
9075344Ssobomax			}
9175344Ssobomax			bcopy(tbuffer, bp, tpos);
9275344Ssobomax			pos += tpos;
9375344Ssobomax			bp += tpos;
9475344Ssobomax			if (pos > len)
9575344Ssobomax				return(pos);
9675344Ssobomax		}
972089Ssos	}
982089Ssos	if (!fgets(temp, sizeof(temp), fd) || strcmp(temp, "end\n"))
992089Ssos		return(0);
1002089Ssos	return(pos);
1012089Ssos}
102