/*
* $Id: ssvn_device.c,v 1.4 2025/03/09 19:50:47 snw Exp $
* ^$DEVICE ssvn
*
*
* Author: Serena Willis <snw@coherent-logic.com>
* Copyright (C) 1998 MUG Deutschland
* Copyright (C) 2020, 2025 Coherent Logic Development LLC
*
*
* This file is part of FreeM.
*
* FreeM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero Public License for more details.
*
* You should have received a copy of the GNU Affero Public License
* along with FreeM. If not, see <https://www.gnu.org/licenses/>.
*
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mref.h"
#include "mpsdef.h"
void set_dsw_bit(int bit);
void clear_dsw_bit(int bit);
void ssvn_device(short action, char *key, char *data)
{
int channel;
int fd;
int i;
FILE *fp;
freem_ref_t *r;
char *dbuf;
char *envbuf;
r = (freem_ref_t *) malloc (sizeof (freem_ref_t));
NULLPTRCHK(r,"ssvn_device");
dbuf = (char *) malloc (100 * sizeof (char));
NULLPTRCHK(dbuf,"ssvn_device");
mref_init (r, MREF_RT_SSV, "^$DEVICE");
internal_to_mref (r, key);
if (!isdigit (r->subscripts[0][0])) {
merr_raise (NODEVICE);
goto done;
}
strcpy (dbuf, r->subscripts[0]);
stcnv_c2m (dbuf);
channel = intexpr (dbuf);
if (channel < 0 || channel >= MAXDEV) {
merr_raise (NODEVICE);
goto done;
}
for (i = 0; i < strlen (r->subscripts[1]); i++) r->subscripts[1][i] = toupper (r->subscripts[1][i]);
fp = opnfile[channel];
if (channel != 0 && (fp == NULL || (fd = fileno (fp)) == -1) && channel < FIRSTSCK && strcmp (r->subscripts[1], "$DEVICE") != 0) {
merr_raise (NOPEN);
goto done;
}
key = mref_to_internal (r);
switch (action) {
case get_sym:
if (r->subscript_count == 1) {
stcpy (data, dev[channel]);
break;
}
if (r->subscript_count == 2) {
if (strcmp (r->subscripts[1], "$DEVICE") == 0) {
if (devstat[channel].mdc_err == 0) {
snprintf (data, 3, "0\201\0");
}
else {
snprintf (data, 120, "%d,%d,%s\201\0", devstat[channel].mdc_err, devstat[channel].frm_err, devstat[channel].err_txt);
}
break;
}
if (strcmp (r->subscripts[1], "EOF") == 0 && channel != 0) {
if (feof (fp)) {
sprintf (data, "1\201");
}
else {
sprintf (data, "0\201");
}
break;
}
else if (strcmp (r->subscripts[1], "INPUT_BUFFER") == 0) {
stcpy (data, ug_buf[channel]);
break;
}
else if ((strcmp (r->subscripts[1], "$X") == 0)) {
sprintf (data, "%d\201", xpos[channel]);
break;
}
else if ((strcmp (r->subscripts[1], "$Y") == 0)) {
sprintf (data, "%d\201", ypos[channel]);
break;
}
else if ((strcmp (r->subscripts[1], "ROWS") == 0) && (channel == 0)) {
sprintf (data, "%d\201", n_lines);
break;
}
else if ((strcmp (r->subscripts[1], "COLUMNS") == 0) && (channel == 0)) {
sprintf (data, "%d\201", n_columns);
break;
}
else if (strcmp (r->subscripts[1], "FD") == 0) {
sprintf (data, "%d\201", fileno (fp));
break;
}
else if (strcmp (r->subscripts[1], "MODE") == 0) {
switch (sq_modes[channel]) {
case 'r':
sprintf (data, "READ\201");
break;
case 'w':
sprintf (data, "WRITE\201");
break;
case 'a':
sprintf (data, "APPEND\201");
break;
case '+':
sprintf (data, "READWRITE\201");
break;
default:
sprintf (data, "\201");
break;
}
}
else if (strcmp (r->subscripts[1], "CHARACTER") == 0) {
sprintf (data, "M\201");
break;
}
else if (strcmp (r->subscripts[1], "NAME") == 0) {
sprintf (data, "%s", dev[channel]);
break;
}
else if (strcmp (r->subscripts[1], "TYPE") == 0) {
if (channel == 0) {
sprintf (data, "4,TERMINAL\201");
}
else if (channel > 0 && channel < FIRSTSCK) {
sprintf (data, "1,FILE\201");
}
else {
sprintf (data, "2,SOCKET\201");
}
break;
}
else if (strcmp (r->subscripts[1], "LENGTH") == 0 && channel != 0) {
struct stat s;
off_t siz;
fstat (fd, &s);
siz = s.st_size;
sprintf (data, "%ld\201", (long) siz);
break;
}
else if (strcmp (r->subscripts[1], "NAMESPACE") == 0) {
switch (channel) {
case 0:
sprintf (data, "X364\201");
break;
default:
sprintf (data, "\201");
break;
}
break;
}
else {
merr_raise (M38);
goto done;
}
goto done;
}
if ((r->subscript_count == 3) && (strcmp (r->subscripts[1], "OPTIONS") == 0)) {
if (strcmp (r->subscripts[2], "DSW") == 0 && channel == 0) {
sprintf (data, "%ld\201", DSW);
merr_raise (OK);
goto done;
}
else if (strcmp (r->subscripts[2], "TERMINATOR") == 0) {
symtab (get_sym, key, data);
goto done;
}
else if (strcmp (r->subscripts[2], "TERMID") == 0 && channel == 0) {
envbuf = getenv ("TERM");
strcpy (data, envbuf);
stcnv_c2m (data);
goto done;
}
else if (strcmp (r->subscripts[2], "ECHO") == 0 && channel == 0) {
if (ECHOON) {
sprintf (data, "1\201");
}
else {
sprintf (data, "0\201");
}
}
else if (strcmp (r->subscripts[2], "DELMODE") == 0 && channel == 0) {
if (DELMODE) {
sprintf (data, "1\201");
}
else {
sprintf (data, "0\201");
}
}
else if (strcmp (r->subscripts[2], "ESCAPE") == 0 && channel == 0) {
if (ESCSEQPROC) {
sprintf (data, "1\201");
}
else {
sprintf (data, "0\201");
}
}
else if (strcmp (r->subscripts[2], "CONVUPPER") == 0 && channel == 0) {
if (CONVUPPER) {
sprintf (data, "1\201");
}
else {
sprintf (data, "0\201");
}
}
else if (strcmp (r->subscripts[2], "DELEMPTY") == 0 && channel == 0) {
if (DELEMPTY) {
sprintf (data, "1\201");
}
else {
sprintf (data, "0\201");
}
}
else if (strcmp (r->subscripts[2], "NOCTRLS") == 0 && channel == 0) {
if (NOCTRLS) {
sprintf (data, "1\201");
}
else {
sprintf (data, "0\201");
}
}
else if (strcmp (r->subscripts[2], "CTRLOPROC") == 0 && channel == 0) {
if (CTRLOPROC) {
sprintf (data, "1\201");
}
else {
sprintf (data, "0\201");
}
}
else if (strcmp (r->subscripts[2], "NOTYPEAHEAD") == 0 && channel == 0) {
if (NOTYPEAHEAD) {
sprintf (data, "1\201");
}
else {
sprintf (data, "0\201");
}
}
else {
merr_raise (M38);
goto done;
}
break;
}
else {
merr_raise (M38);
goto done;
}
case set_sym:
if (r->subscript_count == 2) {
if (strcmp (r->subscripts[1], "DSW") == 0 && channel == 0) {
stcpy (dbuf, data);
stcnv_m2c (dbuf);
DSW = atol (dbuf);
merr_raise (OK);
goto done;
}
else if (strcmp (r->subscripts[1], "INPUT_BUFFER") == 0) {
stcpy (ug_buf[channel], data);
merr_raise (OK);
goto done;
}
else {
merr_raise (M29);
goto done;
}
}
if ((r->subscript_count == 3) && (strcmp (r->subscripts[1], "OPTIONS") == 0)) {
if (strcmp (r->subscripts[2], "ECHO") == 0 && channel == 0) {
if (tvexpr (data)) {
clear_dsw_bit (0);
}
else {
set_dsw_bit (0);
}
}
else if (strcmp (r->subscripts[2], "TERMINATOR") == 0) {
symtab (set_sym, key, data);
merr_raise (OK);
goto done;
}
else if (strcmp (r->subscripts[2], "DELMODE") == 0 && channel == 0) {
if (tvexpr (data)) {
set_dsw_bit (2);
}
else {
clear_dsw_bit (2);
}
}
else if (strcmp (r->subscripts[2], "ESCAPE") == 0 && channel == 0) {
if (tvexpr (data)) {
set_dsw_bit (6);
}
else {
clear_dsw_bit (6);
}
}
else if (strcmp (r->subscripts[2], "CONVUPPER") == 0 && channel == 0) {
if (tvexpr (data)) {
set_dsw_bit (14);
}
else {
clear_dsw_bit (14);
}
}
else if (strcmp (r->subscripts[2], "DELEMPTY") == 0 && channel == 0) {
if (tvexpr (data)) {
set_dsw_bit (19);
}
else {
clear_dsw_bit (19);
}
}
else if (strcmp (r->subscripts[2], "NOCTRLS") == 0 && channel == 0) {
if (tvexpr (data)) {
set_dsw_bit (20);
}
else {
clear_dsw_bit (20);
}
}
else if (strcmp (r->subscripts[2], "CTRLOPROC") == 0 && channel == 0) {
if (tvexpr (data)) {
set_dsw_bit (21);
}
else {
clear_dsw_bit (21);
}
}
else if (strcmp (r->subscripts[2], "NOTYPEAHEAD") == 0 && channel == 0) {
if (tvexpr (data)) {
set_dsw_bit (25);
}
else {
clear_dsw_bit (25);
}
}
else {
merr_raise (M29);
goto done;
}
break;
}
default:
merr_raise (INVREF);
break;
}
done:
free (key);
free (r);
free (dbuf);
return;
}
void set_dsw_bit(int bit)
{
DSW = ((1 << bit) | DSW);
}
void clear_dsw_bit(int bit)
{
DSW &= ~(1 << bit);
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>