~ubuntu-branches/ubuntu/precise/hercules/precise

« back to all changes in this revision

Viewing changes to panel.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter De Schrijver (p2)
  • Date: 2005-10-24 01:38:32 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051024013832-8udp54rojxzvvxx8
Tags: 3.0.2-1
* New maintainer
* New upstream release (Closes: #289121, #184217, #241064, #251287)
* Remove x3270 from suggests (Closes: #318130)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* PANEL.C      (c) Copyright Roger Bowler, 1999-2003                */
 
1
/* PANEL.C      (c) Copyright Roger Bowler, 1999-2004                */
2
2
/*              ESA/390 Control Panel Commands                       */
3
3
/*                                                                   */
4
4
/*              Modified for New Panel Display =NP=                  */
5
5
/*-------------------------------------------------------------------*/
6
6
/* This module is the control panel for the ESA/390 emulator.        */
7
 
/* It provides functions for displaying the PSW and registers        */
8
 
/* and a command line for requesting control operations such         */
9
 
/* as IPL, stop, start, single stepping, instruction tracing,        */
10
 
/* and storage displays. It displays messages issued by other        */
11
 
/* threads via the logmsg macro, and optionally also writes          */
12
 
/* all messages to a log file if stdout is redirected.               */
 
7
/* It provides a command interface into hercules, and it displays    */
 
8
/* messages that are issued by various hercules components.          */
13
9
/*-------------------------------------------------------------------*/
14
10
 
15
11
/*-------------------------------------------------------------------*/
21
17
/*      Set/reset bad frame indicator command by Jan Jaeger          */
22
18
/*      attach/detach/define commands by Jan Jaeger                  */
23
19
/*      Panel refresh rate triva by Reed H. Petty                    */
24
 
/* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2003      */
 
20
/* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2004      */
25
21
/*      64-bit address support by Roger Bowler                       */
26
22
/*      Display subchannel command by Nobumichi Kozawa               */
27
23
/*      External GUI logic contributed by "Fish" (David B. Trout)    */
30
26
/*-------------------------------------------------------------------*/
31
27
 
32
28
#include "hercules.h"
33
 
 
34
29
#include "devtype.h"
35
 
 
36
30
#include "opcode.h"
37
 
 
 
31
#include "history.h"
38
32
// #include "inline.h"
39
 
 
40
 
#if defined(OPTION_FISHIO)
41
 
#include "w32chan.h"
42
 
#endif /* defined(OPTION_FISHIO) */
43
 
 
44
 
#if defined(FISH_HANG)
45
 
extern  int   bFishHangAtExit;  // (set to true when shutting down)
46
 
extern  void  FishHangInit(char* pszFileCreated, int nLineCreated);
47
 
extern  void  FishHangReport();
48
 
extern  void  FishHangAtExit();
49
 
#endif // defined(FISH_HANG)
 
33
#include "fillfnam.h"
50
34
 
51
35
#define  DISPLAY_INSTRUCTION_OPERANDS
52
36
 
53
 
 
54
 
/* (Socket Devices...) */
55
 
int bind_device (DEVBLK* dev, char* spec);
56
 
int unbind_device (DEVBLK* dev);
57
 
int unix_socket (char* path);
58
 
int inet_socket (char* spec);
59
 
int add_socket_devices_to_fd_set (fd_set* mask, int maxfd);
60
 
void check_socket_devices_for_connections (fd_set* mask);
61
 
void socket_device_connection_handler (bind_struct* bs);
62
 
char* safe_strdup (char* str);
63
 
 
64
 
 
65
37
/*=NP================================================================*/
66
38
/* Global data for new panel display                                 */
67
39
/*   (Note: all NPD mods are identified by the string =NP=           */
109
81
#define ANSI_CLEAR_EOL "\x1B[K"
110
82
#define ANSI_CURSOR "\x1B[%d;%dH"
111
83
 
112
 
int NPDup = 0;          /* 1 when new panel is up */
113
 
int NPDinit = 0;        /* 1 when new panel is initialized */
114
 
int NPhelpup = 0;       /* 1 when displaying help panel */
115
 
int NPhelpdown = 0;     /* 1 when the help panel is brought down */
116
 
int NPregdisp = 0;      /* which regs are displayed 0=gpr, 1=cr, 2=ar, 3=fpr */
117
 
int NPaddress = 0;      /* Address switches */
118
 
int NPdata = 0;         /* Data switches */
119
 
int NPipl = 0;          /* IPL address switches */
120
 
 
121
 
int NPcmd = 0;          /* 1 when command mode for NP is in effect */
122
 
int NPdataentry = 0;    /* 1 when data entry for NP is in progress */
123
 
int NPdevsel = 0;       /* 1 when device selection is in progress */
 
84
/*-------------------------------------------------------------------*/
 
85
/* Definitions for ANSI control sequences                            */
 
86
/*-------------------------------------------------------------------*/
 
87
#define ANSI_SAVE_CURSOR        "\x1B[s"
 
88
#define ANSI_CURSOR_UP          "\x1B[1A"
 
89
#define ANSI_CURSOR_DOWN        "\x1B[1B"
 
90
#define ANSI_CURSOR_FORWARD     "\x1B[1C"
 
91
#define ANSI_CURSOR_BACKWARD    "\x1B[1D"
 
92
#define ANSI_POSITION_CURSOR    "\x1B[%d;%dH"
 
93
#define ANSI_ROW1_COL1          "\x1B[1;1H"
 
94
#define ANSI_ROW1_COL80         "\x1B[1;80H"
 
95
#define ANSI_ROW22_COL80        "\x1B[22;80H"
 
96
#define ANSI_ROW23_COL1         "\x1B[23;1H"
 
97
#define ANSI_ROW24_COL1         "\x1B[24;1H"
 
98
#define ANSI_ROW24_COL79        "\x1B[24;79H"
 
99
#define ANSI_BLACK_GREEN        "\x1B[30;42m"
 
100
#define ANSI_YELLOW_RED         "\x1B[33;1;41m"
 
101
#define ANSI_WHITE_BLACK        "\x1B[0m"
 
102
#define ANSI_HIGH_INTENSITY     "\x1B[1m"
 
103
#define ANSI_ERASE_EOL          "\x1B[K"
 
104
#define ANSI_ERASE_SCREEN       "\x1B[2J"
 
105
#define ANSI_RESTORE_CURSOR     "\x1B[u"
 
106
 
 
107
/*-------------------------------------------------------------------*/
 
108
/* Definitions for keyboard input sequences                          */
 
109
/*-------------------------------------------------------------------*/
 
110
#define KBD_HOME                "\x1B[1~"
 
111
#define KBD_INSERT              "\x1B[2~"
 
112
#define KBD_DELETE              "\x1B[3~"
 
113
#define KBD_END                 "\x1B[4~"
 
114
#define KBD_PAGE_UP             "\x1B[5~"
 
115
#define KBD_PAGE_DOWN           "\x1B[6~"
 
116
#define KBD_UP_ARROW            "\x1B[A"
 
117
#define KBD_DOWN_ARROW          "\x1B[B"
 
118
#define KBD_RIGHT_ARROW         "\x1B[C"
 
119
#define KBD_LEFT_ARROW          "\x1B[D"
 
120
#define xKBD_UP_ARROW           "\x1BOA"
 
121
#define xKBD_DOWN_ARROW         "\x1BOB"
 
122
#define xKBD_RIGHT_ARROW        "\x1BOC"
 
123
#define xKBD_LEFT_ARROW         "\x1BOD"
 
124
 
 
125
#define ANSI_RESET_WHT_BLK   "\x1B[0;37;40m"
 
126
#define ANSI_CLEAR_SCREEN    "\x1B[2J"
 
127
 
 
128
int  NPDup = 0;         /* 1 when new panel is up */
 
129
int  NPDinit = 0;       /* 1 when new panel is initialized */
 
130
int  NPhelpup = 0;      /* 1 when displaying help panel */
 
131
int  NPhelpdown = 0;    /* 1 when the help panel is brought down */
 
132
int  NPregdisp = 0;     /* which regs are displayed 0=gpr, 1=cr, 2=ar, 3=fpr */
 
133
int  NPaddress = 0;     /* Address switches */
 
134
int  NPdata = 0;        /* Data switches */
 
135
int  NPipl = 0;         /* IPL address switches */
 
136
 
 
137
int  NPcmd = 0;         /* 1 when command mode for NP is in effect */
 
138
int  NPdataentry = 0;   /* 1 when data entry for NP is in progress */
 
139
int  NPdevsel = 0;      /* 1 when device selection is in progress */
124
140
char NPpending;         /* Command which is pending data entry */
125
141
char NPentered[128];    /* Data which was entered */
126
142
char NPprompt1[40];     /* Prompts for left and right bottom of screen */
127
143
char NPprompt2[40];
128
144
char NPsel2;            /* Command letter to trigger 2nd phase of dev sel */
129
145
char NPdevice;          /* Which device selected */
130
 
int NPasgn;             /* Index to device being reassigned */
131
 
int NPlastdev;          /* Number of devices */
132
 
int NPdevaddr[24];      /* current device addresses */
 
146
int  NPasgn;            /* Index to device being reassigned */
 
147
int  NPlastdev;         /* Number of devices */
 
148
int  NPdevaddr[24];     /* current device addresses */
133
149
char NPdevstr[16];      /* device - stringed */
134
150
 
135
151
/* the following fields are current states, to detect changes and redisplay */
136
152
 
137
153
char NPstate[24];       /* Current displayed CPU state */
138
 
U32 NPregs[16];         /* Current displayed reg values */
139
 
int NPbusy[24];         /* Current busy state of displayed devices */
140
 
int NPpend[24];         /* Current int pending state */
141
 
int NPopen[24];         /* Current open state */
142
 
int NPonline[24];       /* Current online state of devices */
143
 
char NPdevname[24][128]; /* Current name assignments */
144
 
int NPcuraddr;          /* current addr switches */
145
 
int NPcurdata;          /* current data switches */
146
 
int NPcurrg;            /* current register set displayed */
147
 
int NPcuripl;           /* current IPL switches */
148
 
int NPcurpos[2];        /* Cursor position (row, col) */
 
154
U32  NPregs[16];        /* Current displayed reg values */
 
155
int  NPbusy[24];        /* Current busy state of displayed devices */
 
156
int  NPpend[24];        /* Current int pending state */
 
157
int  NPopen[24];        /* Current open state */
 
158
int  NPonline[24];      /* Current online state of devices */
 
159
char NPdevname[24][128];/* Current name assignments */
 
160
int  NPcuraddr;         /* current addr switches */
 
161
int  NPcurdata;         /* current data switches */
 
162
int  NPcurrg;           /* current register set displayed */
 
163
int  NPcuripl;          /* current IPL switches */
 
164
int  NPcurpos[2];       /* Cursor position (row, col) */
149
165
char NPcolor[24];       /* color string */
150
 
int NPdatalen;          /* Length of data */
 
166
int  NPdatalen;         /* Length of data */
151
167
char NPcurprompt1[40];
152
168
char NPcurprompt2[40];
153
 
U32 NPaaddr;
154
 
 
155
 
#ifdef EXTERNALGUI
156
 
/*-------------------------------------------------------------------*/
157
 
/* External GUI control                                              */
158
 
/*-------------------------------------------------------------------*/
159
 
#ifdef OPTION_MIPS_COUNTING
160
 
U32     mipsrate = 0;
161
 
U32     siosrate = 0;
162
 
U32     prevmipsrate = 0;
163
 
U32     prevsiosrate = 0;
164
 
int     gui_cpupct = 0;                 /* 1=cpu percentage active   */
165
 
#endif /*OPTION_MIPS_COUNTING*/
166
 
int     gui_gregs = 1;                  /* 1=gregs status active     */
167
 
int     gui_cregs = 1;                  /* 1=cregs status active     */
168
 
int     gui_aregs = 1;                  /* 1=aregs status active     */
169
 
int     gui_fregs = 1;                  /* 1=fregs status active     */
170
 
int     gui_devlist = 1;                /* 1=devlist status active   */
171
 
DEVBLK* dev;
172
 
BYTE*   devclass;
173
 
char    devnam[256];
174
 
int     stat_online, stat_busy, stat_pend, stat_open;
175
 
#endif /*EXTERNALGUI*/
 
169
U32  NPaaddr;
 
170
 
 
171
#define MAX_MSGS                800     /* Number of slots in buffer */
 
172
#define MSG_SIZE                80      /* Size of one message       */
 
173
#define BUF_SIZE    (MAX_MSGS*MSG_SIZE) /* Total size of buffer      */
 
174
#define NUM_LINES               22      /* Number of scrolling lines */
 
175
#define CMD_SIZE             32767      /* Length of command line    */
 
176
 
 
177
static int     firstmsgn = 0;           /* Number of first message to
 
178
                                           be displayed relative to
 
179
                                           oldest message in buffer  */
 
180
static BYTE   *msgbuf;                  /* Circular message buffer   */
 
181
static int     msgslot = 0;             /* Next available buffer slot*/
 
182
static int     nummsgs = 0;             /* Number of msgs in buffer  */
 
183
 
 
184
#if 1
 
185
//
 
186
//
 
187
//  THE FOLLOWING CODE IS HERE TO PROVIDE COMPATIBILIY WITH THE CURRENT
 
188
//  PANEL IMPLEMENTATION
 
189
//
 
190
//  THE PANEL DISPLAY SHOULD AT SOME POINT BE REWRITTEN TO USE LOG_LINE
 
191
//  AND LOG_READ RATHER THEN THE MESSAGE PIPE PROVIDED HERE
 
192
//
 
193
//
 
194
FILE   *compat_msgpipew;                /* Message pipe write handle */
 
195
int     compat_msgpiper;                /* Message pipe read handle  */
 
196
int     compat_shutdown;                /* Shutdown flag             */
 
197
TID     compat_tid = 0;
 
198
 
 
199
#if defined(OPTION_DYNAMIC_LOAD)
 
200
void *(*panel_command) (void *);
 
201
void  (*panel_display) (void);
 
202
void  (*daemon_task) (void);
 
203
int   (*config_command) (int argc, char *argv[], char *cmdline);
 
204
int   (*system_command) (int argc, char *argv[], char *cmdline);
 
205
void *(*debug_cpu_state) (REGS *);
 
206
void *(*debug_device_state) (DEVBLK *);
 
207
void *(*debug_program_interrupt) (REGS *, int);
 
208
void *(*debug_diagnose) (U32, int, int, REGS *);
 
209
void *(*debug_sclp_unknown_command) (U32, void *, REGS *);
 
210
void *(*debug_sclp_unknown_event) (void *, void *, REGS *);
 
211
void *(*debug_sclp_event_data) (void *, void *, REGS *);
 
212
void *(*debug_chsc_unknown_request) (void *, void *, REGS *);
 
213
void *(*debug_watchdog_signal) (REGS *);
 
214
#endif
 
215
 
 
216
static char *lmsbuf;
 
217
static int   lmsnum;
 
218
static int   lmscnt;
 
219
static void *panel_compat_thread(void *arg)
 
220
{
 
221
 
 
222
    UNREFERENCED(arg);
 
223
 
 
224
    while(!compat_shutdown)
 
225
        if((lmscnt = log_read(&lmsbuf, &lmsnum, LOG_BLOCK)))
 
226
            fwrite(lmsbuf,lmscnt,1,compat_msgpipew);
 
227
 
 
228
    fclose(compat_msgpipew);
 
229
 
 
230
    return NULL;
 
231
}
 
232
 
 
233
 
 
234
static void panel_compat_init()
 
235
{
 
236
ATTR compat_attr;
 
237
int rc, pfd[2];
 
238
 
 
239
    rc = pipe (pfd);
 
240
    if (rc < 0)
 
241
    {
 
242
        logmsg(_("HHCLG013S Message pipe creation failed: %s\n"),
 
243
                strerror(errno));
 
244
        exit(1);
 
245
    }
 
246
 
 
247
    compat_shutdown = 0;
 
248
    compat_msgpiper = pfd[0];
 
249
    compat_msgpipew = fdopen (pfd[1], "w");
 
250
    if (compat_msgpipew == NULL)
 
251
    {
 
252
        compat_msgpipew = stderr;
 
253
        logmsg(_("HHCLG014S Message pipe open failed: %s\n"),
 
254
                strerror(errno));
 
255
        exit(1);
 
256
    }
 
257
    setvbuf (compat_msgpipew, NULL, _IOLBF, 0);
 
258
 
 
259
    initialize_detach_attr (&compat_attr);
 
260
 
 
261
    create_thread(&compat_tid, &compat_attr, panel_compat_thread, NULL);
 
262
}
 
263
#endif
176
264
 
177
265
/*=NP================================================================*/
178
266
/*  Initialize the NP data                                           */
210
298
{
211
299
 
212
300
    DEVBLK *dev;
213
 
    BYTE *devclass;
 
301
    char *devclass;
214
302
    int p, a;
215
303
    char c[2];
216
304
    char devnam[128];
219
307
    fprintf(confp, ANSI_CLEAR);
220
308
    fprintf(confp, ANSI_WHT_BLU);
221
309
    fprintf(confp, ANSI_CURSOR, 1, 1);
222
 
    fprintf(confp, " Hercules        CPU         %7.7s ",
 
310
    fprintf(confp, " Hercules   CPU              %7.7s ",
223
311
                                        get_arch_mode_string(NULL));
224
312
    fprintf(confp, ANSI_CURSOR, 1, 38);
225
313
    fprintf(confp, "|             Peripherals                  ");
337
425
    REGS *regs;
338
426
    BYTE pswwait;                        /* PSW wait state bit        */
339
427
    DEVBLK *dev;
340
 
    BYTE *devclass;
 
428
    char *devclass;
341
429
    int p, a;
342
430
    char ch[2];
343
431
    U32 aaddr;
344
432
    int savadr;
345
 
#ifdef OPTION_MIPS_COUNTING
346
 
    U32 mipsrate;
347
 
    U32 siosrate;
348
 
#endif
349
433
 
350
434
    if (NPhelpup == 1) {
351
435
        if (NPhelpdown == 1) {
384
468
        return;
385
469
        }
386
470
    }
387
 
    regs = sysblk.regs + sysblk.pcpu;
 
471
 
 
472
    regs = sysblk.regs[sysblk.pcpu];
 
473
    if (!regs) regs = &sysblk.dummyregs;
388
474
 
389
475
#if defined(OPTION_MIPS_COUNTING)
390
476
    fprintf(confp, ANSI_WHT_BLU);
400
486
#endif /*defined(_FEATURE_SIE)*/
401
487
 
402
488
    memset (curpsw, 0x00, sizeof(curpsw));
403
 
    store_psw (regs, curpsw);
 
489
    copy_psw (regs, curpsw);
 
490
    if( regs->arch_mode == ARCH_900 )
 
491
    {
 
492
        curpsw[1] |= 0x08;
 
493
        curpsw[4] |= curpsw[12];
 
494
        curpsw[5] |= curpsw[13];
 
495
        curpsw[6] |= curpsw[14];
 
496
        curpsw[7] |= curpsw[15];
 
497
        if(regs->psw.IA_G > 0x7FFFFFFFULL)
 
498
            curpsw[7] |= 0x01;
 
499
    }
404
500
    pswwait = curpsw[1] & 0x02;
405
501
    fprintf (confp, ANSI_YLW_BLK);
406
502
    fprintf (confp, ANSI_CURSOR, 3, 2);
413
509
                    pswwait ? 'W' : '.',
414
510
                    regs->loadstate ? 'L' : '.',
415
511
                    regs->checkstop ? 'C' : '.',
416
 
                    regs->psw.prob ? 'P' : '.',
 
512
                    PROBSTATE(&regs->psw) ? 'P' : '.',
417
513
#if defined(_FEATURE_SIE)
418
 
                    regs->sie_state ? 'S' : '.',
 
514
                    SIE_MODE(regs) ? 'S' : '.',
419
515
#else /*!defined(_FEATURE_SIE)*/
420
516
                    '.',
421
517
#endif /*!defined(_FEATURE_SIE)*/
452
548
                }
453
549
                break;
454
550
            case 4:
455
 
                aaddr = APPLY_PREFIXING (NPaddress, regs->PX);
 
551
                aaddr = APPLY_PREFIXING ((U32)NPaddress, regs->PX);
456
552
                if (aaddr > regs->mainlim)
457
553
                    break;
458
554
                curreg[i] = 0;
485
581
    fprintf(confp, ANSI_CURSOR, 19, 2);
486
582
    fprintf(confp, ANSI_YLW_BLK);
487
583
#ifdef OPTION_MIPS_COUNTING
488
 
#ifdef _FEATURE_CPU_RECONFIG
489
 
    for(mipsrate = siosrate = i = 0; i < MAX_CPU_ENGINES; i++)
490
 
      if(sysblk.regs[i].cpuonline)
491
 
#else /*!_FEATURE_CPU_RECONFIG*/
492
 
    for(mipsrate = siosrate = i = 0; i < sysblk.numcpu; i++)
493
 
#endif /*!_FEATURE_CPU_RECONFIG*/
494
 
    {
495
 
        mipsrate += sysblk.regs[i].mipsrate;
496
 
        siosrate += sysblk.regs[i].siosrate;
497
 
    }
498
 
    if (mipsrate > 100000) mipsrate = 0;        /* ignore wildly high rate */
499
584
    fprintf(confp, "%2.1d.%2.2d  %5d",
500
 
            mipsrate / 1000, (mipsrate % 1000) / 10,
501
 
           siosrate);
 
585
            sysblk.mipsrate / 1000, (sysblk.mipsrate % 1000) / 10,
 
586
            sysblk.siosrate);
502
587
#else
503
588
    fprintf(confp, "%12.12u",
504
589
#if defined(_FEATURE_SIE)
505
 
        regs->sie_state ? (unsigned)regs->hostregs->instcount :
 
590
        SIE_MODE(regs) ? (unsigned)regs->hostregs->instcount :
506
591
#endif /*defined(_FEATURE_SIE)*/
507
592
        (unsigned)regs->instcount);
508
593
#endif
565
650
                  (strlen(dev->filename) > 0))
566
651
                       online = 1;
567
652
         if (dev->busy) busy = 1;
568
 
         if (dev->pending) pend = 1;
 
653
         if (IOPENDING(dev)) pend = 1;
569
654
         if (dev->fd > 2) open = 1;
570
655
         if (online != NPonline[a - 1]) {
571
656
              fprintf(confp, ANSI_CURSOR, p, 40);
658
743
/* ==============   End of the main NP block of code    =============*/
659
744
 
660
745
 
661
 
/*-------------------------------------------------------------------*/
662
 
/* Definitions for ANSI control sequences                            */
663
 
/*-------------------------------------------------------------------*/
664
 
#define ANSI_SAVE_CURSOR        "\x1B[s"
665
 
#define ANSI_CURSOR_UP          "\x1B[1A"
666
 
#define ANSI_CURSOR_DOWN        "\x1B[1B"
667
 
#define ANSI_CURSOR_FORWARD     "\x1B[1C"
668
 
#define ANSI_CURSOR_BACKWARD    "\x1B[1D"
669
 
#define ANSI_POSITION_CURSOR    "\x1B[%d;%dH"
670
 
#define ANSI_ROW1_COL1          "\x1B[1;1H"
671
 
#define ANSI_ROW1_COL80         "\x1B[1;80H"
672
 
#define ANSI_ROW22_COL80        "\x1B[22;80H"
673
 
#define ANSI_ROW23_COL1         "\x1B[23;1H"
674
 
#define ANSI_ROW24_COL1         "\x1B[24;1H"
675
 
#define ANSI_ROW24_COL79        "\x1B[24;79H"
676
 
#define ANSI_BLACK_GREEN        "\x1B[30;42m"
677
 
#define ANSI_YELLOW_RED         "\x1B[33;1;41m"
678
 
#define ANSI_WHITE_BLACK        "\x1B[0m"
679
 
#define ANSI_HIGH_INTENSITY     "\x1B[1m"
680
 
#define ANSI_ERASE_EOL          "\x1B[K"
681
 
#define ANSI_ERASE_SCREEN       "\x1B[2J"
682
 
#define ANSI_RESTORE_CURSOR     "\x1B[u"
683
 
 
684
 
/*-------------------------------------------------------------------*/
685
 
/* Definitions for keyboard input sequences                          */
686
 
/*-------------------------------------------------------------------*/
687
 
#define KBD_HOME                "\x1B[1~"
688
 
#define KBD_INSERT              "\x1B[2~"
689
 
#define KBD_DELETE              "\x1B[3~"
690
 
#define KBD_END                 "\x1B[4~"
691
 
#define KBD_PAGE_UP             "\x1B[5~"
692
 
#define KBD_PAGE_DOWN           "\x1B[6~"
693
 
#define KBD_UP_ARROW            "\x1B[A"
694
 
#define KBD_DOWN_ARROW          "\x1B[B"
695
 
#define KBD_RIGHT_ARROW         "\x1B[C"
696
 
#define KBD_LEFT_ARROW          "\x1B[D"
697
 
 
698
 
/*-------------------------------------------------------------------*/
699
 
/* Cleanup routine                                                   */
700
 
/*-------------------------------------------------------------------*/
701
 
static void system_cleanup (void)
 
746
static void panel_cleanup(void *unused __attribute__ ((unused)) )
702
747
{
703
748
struct termios kbattr;                  /* Terminal I/O structure    */
 
749
int i,n;
 
750
char c;
 
751
 
 
752
    compat_shutdown = 1;
 
753
    log_wakeup(NULL);
704
754
 
705
755
    /* Restore the terminal mode */
706
756
    tcgetattr (STDIN_FILENO, &kbattr);
707
757
    kbattr.c_lflag |= (ECHO | ICANON);
708
758
    tcsetattr (STDIN_FILENO, TCSANOW, &kbattr);
709
759
 
710
 
#ifdef EXTERNALGUI
711
 
    if (!extgui)
712
 
#endif /*EXTERNALGUI*/
713
 
    /* Reset the cursor position */
714
 
    fprintf (stderr,
715
 
            ANSI_ROW24_COL79
716
 
            ANSI_WHITE_BLACK
717
 
            "\n");
718
 
    fprintf (stderr,
719
 
            "HHCIN007I Hercules terminated\n");
720
 
 
721
 
} /* end function system_cleanup */
722
 
 
723
 
/*-------------------------------------------------------------------*/
724
 
/* Process .RC file thread                                           */
725
 
/*-------------------------------------------------------------------*/
726
 
 
727
 
int rc_thread_done = 0;                 /* 1 = RC file processed     */
728
 
 
729
 
void* process_rc_file (void* dummy)
730
 
{
731
 
BYTE   *rcname;                         /* hercules.rc name pointer  */
732
 
FILE   *rcfp;                           /* RC file pointer           */
733
 
size_t  rcbufsize = 1024;               /* Size of RC file  buffer   */
734
 
BYTE   *rcbuf = NULL;                   /* RC file input buffer      */
735
 
int     rclen;                          /* length of RC file record  */
736
 
int     rc_pause_amt = 0;               /* seconds to pause RC file  */
737
 
BYTE   *p;                              /* (work)                    */
738
 
 
739
 
    UNREFERENCED(dummy);
740
 
 
741
 
    /* Obtain the name of the hercules.rc file or default */
742
 
 
743
 
    if(!(rcname = getenv("HERCULES_RC")))
744
 
        rcname = "hercules.rc";
745
 
 
746
 
    /* Open RC file. If it doesn't exist,
747
 
       then there's nothing for us to do */
748
 
 
749
 
    if (!(rcfp = fopen(rcname, "r")))
750
 
    {
751
 
        if (ENOENT != errno)
752
 
            logmsg(_("HHCPN007E RC file %s open failed: %s\n"),
753
 
                rcname, strerror(errno));
754
 
        rc_thread_done = 1;
755
 
        return NULL;
756
 
    }
757
 
 
758
 
    logmsg(_("HHCPN008I RC file processing thread started using file %s\n"),
759
 
           rcname);
760
 
 
761
 
    /* Obtain storage for the RC file buffer */
762
 
 
763
 
    if (!(rcbuf = malloc (rcbufsize)))
764
 
    {
765
 
        logmsg(_("HHCPN009E RC file buffer malloc failed: %s\n"),
766
 
            strerror(errno));
767
 
        fclose(rcfp);
768
 
        rc_thread_done = 1;
769
 
        return NULL;
770
 
    }
771
 
 
772
 
    for (;;)
773
 
    {
774
 
        /* Read a complete line from the RC file */
775
 
 
776
 
        if (!fgets(rcbuf, rcbufsize, rcfp)) break;
777
 
 
778
 
        /* Remove trailing whitespace */
779
 
 
780
 
        for (rclen = strlen(rcbuf); rclen && isspace(rcbuf[rclen-1]); rclen--);
781
 
        rcbuf[rclen] = 0;
782
 
 
783
 
        /* '#' == silent comment, '*' == loud comment */
784
 
 
785
 
        if ('#' == rcbuf[0] || '*' == rcbuf[0])
786
 
        {
787
 
            if ('*' == rcbuf[0])
788
 
                logmsg ("> %s",rcbuf);
789
 
            continue;
790
 
        }
791
 
 
792
 
        /* Remove any # comments on the line before processing */
793
 
 
794
 
        if ((p = strchr(rcbuf,'#')) && p > rcbuf)
795
 
            do *p = 0; while (isspace(*--p) && p >= rcbuf);
796
 
 
797
 
        if (strncasecmp(rcbuf,"pause",5) == 0)
798
 
        {
799
 
            sscanf(rcbuf+5, "%d", &rc_pause_amt);
800
 
 
801
 
            if (rc_pause_amt < 0 || rc_pause_amt > 999)
802
 
            {
803
 
                logmsg(_("HHCPN010W Ignoring invalid RC file pause "
804
 
                         "statement: %s\n"),
805
 
                         rcbuf+5);
806
 
                continue;
807
 
            }
808
 
 
809
 
            logmsg (_("HHCPN011I Pausing RC file processing for %d "
810
 
                      "seconds...\n"),
811
 
                      rc_pause_amt);
812
 
            sleep(rc_pause_amt);
813
 
            logmsg (_("HHCPN012I Resuming RC file processing...\n"));
814
 
 
815
 
            continue;
816
 
        }
817
 
 
818
 
        /* Process the command */
819
 
 
820
 
        for (p = rcbuf; isspace(*p); p++);
821
 
 
822
 
        SYNCHRONOUS_PANEL_CMD(p);
823
 
    }
824
 
 
825
 
    if (feof(rcfp))
826
 
        logmsg (_("HHCPN013I EOF reached on RC file. Processing complete.\n"));
827
 
    else
828
 
        logmsg (_("HHCPN014E I/O error reading RC file: %s\n"),
829
 
                 strerror(errno));
830
 
 
831
 
    fclose(rcfp);
832
 
 
833
 
    rc_thread_done = 1;
834
 
 
835
 
    return NULL;
 
760
    fprintf(stderr, ANSI_RESET_WHT_BLK ANSI_CLEAR_SCREEN );
 
761
 
 
762
    /* Reset the first line to be displayed (i.e.
 
763
       "scroll down to the most current message") */
 
764
    firstmsgn = nummsgs - NUM_LINES;
 
765
    if (firstmsgn < 0) firstmsgn = 0;
 
766
 
 
767
    /* Display messages in scrolling area */
 
768
    for (i=0; i < NUM_LINES && firstmsgn + i < nummsgs; i++)
 
769
    {
 
770
        n = (nummsgs < MAX_MSGS) ? 0 : msgslot;
 
771
        n += firstmsgn + i;
 
772
        if (n >= MAX_MSGS) n -= MAX_MSGS;
 
773
        fprintf (stderr,
 
774
                ANSI_POSITION_CURSOR
 
775
                ANSI_WHITE_BLACK,
 
776
                i+1, 1);
 
777
        fwrite (msgbuf + (n * MSG_SIZE), MSG_SIZE, 1, stderr);
 
778
    }
 
779
 
 
780
    /* Read any remaining msgs from the msg pipe */
 
781
    while(read (compat_msgpiper, &c, 1) > 0)
 
782
        fputc(c,stderr);
 
783
 
 
784
    /* Read any remaining msgs from the system log */
 
785
    while((lmscnt = log_read(&lmsbuf, &lmsnum, LOG_NOBLOCK)))
 
786
        fwrite(lmsbuf,lmscnt,1,stderr);
836
787
}
837
788
 
838
789
/*-------------------------------------------------------------------*/
839
790
/* Panel display thread                                              */
840
791
/*                                                                   */
841
792
/* This function runs on the main thread.  It receives messages      */
842
 
/* from other threads and displays them on the screen.  It accepts   */
 
793
/* from the log task and displays them on the screen.  It accepts    */
843
794
/* panel commands from the keyboard and executes them.  It samples   */
844
795
/* the PSW periodically and displays it on the screen status line.   */
845
 
/*                                                                   */
846
 
/* Note that this routine must not attempt to write messages into    */
847
 
/* the message pipe by calling the logmsg function, because this     */
848
 
/* will cause a deadlock when the pipe becomes full during periods   */
849
 
/* of high message activity.  For this reason a separate thread is   */
850
 
/* created to process all commands entered.                          */
851
796
/*-------------------------------------------------------------------*/
852
797
 
853
 
int volatile initdone = 0;           /* Initialization complete flag */
854
 
 
855
 
#define MAX_MSGS                800     /* Number of slots in buffer */
856
 
#define MSG_SIZE                80      /* Size of one message       */
857
 
#define BUF_SIZE    (MAX_MSGS*MSG_SIZE) /* Total size of buffer      */
858
 
#define NUM_LINES               22      /* Number of scrolling lines */
859
 
#define CMD_SIZE             32767      /* Length of command line    */
860
 
BYTE   *msgbuf;                         /* Circular message buffer   */
861
 
int     msgslot = 0;                    /* Next available buffer slot*/
862
 
int     nummsgs = 0;                    /* Number of msgs in buffer  */
863
 
int     msg_size = MSG_SIZE;
864
 
int     max_msgs = MAX_MSGS;
865
 
 
866
 
void get_msgbuf(BYTE **_msgbuf, int *_msgslot, int *_nummsgs, int *_msg_size, int *_max_msgs)
867
 
{
868
 
    *_msgbuf = msgbuf;
869
 
    *_msgslot = msgslot;
870
 
    *_nummsgs = nummsgs;
871
 
    *_msg_size = msg_size;
872
 
    *_max_msgs = max_msgs;
873
 
}
874
 
 
875
 
/* (forward references) */
876
 
#ifdef EXTERNALGUI
877
 
void gui_devlist_status (FILE *confp);
878
 
#endif
879
 
 
 
798
#if defined(OPTION_DYNAMIC_LOAD)
 
799
void panel_display_r (void)
 
800
#else
880
801
void panel_display (void)
 
802
#endif
881
803
{
882
804
int     rc;                             /* Return code               */
883
805
int     i, n;                           /* Array subscripts          */
886
808
QWORD   prvpsw;                         /* Previous PSW              */
887
809
BYTE    prvstate = 0xFF;                /* Previous stopped state    */
888
810
U64     prvicount = 0;                  /* Previous instruction count*/
 
811
#if defined(OPTION_SHARED_DEVICES)
 
812
U32     prvscount = 0;                  /* Previous shrdcount        */
 
813
#endif
889
814
BYTE    pswwait;                        /* PSW wait state bit        */
890
 
int     firstmsgn = 0;                  /* Number of first message to
891
 
                                           be displayed relative to
892
 
                                           oldest message in buffer  */
893
 
#ifdef EXTERNALGUI
894
 
BYTE    redraw_msgs = 0;                /* 1=Redraw message area     */
895
 
BYTE    redraw_cmd = 0;                 /* 1=Redraw command line     */
896
 
BYTE    redraw_status = 0;              /* 1=Redraw status line      */
897
 
#else /*!EXTERNALGUI*/
898
815
BYTE    redraw_msgs;                    /* 1=Redraw message area     */
899
816
BYTE    redraw_cmd;                     /* 1=Redraw command line     */
900
817
BYTE    redraw_status;                  /* 1=Redraw status line      */
901
 
#endif /*EXTERNALGUI*/
902
 
BYTE    readbuf[MSG_SIZE];              /* Message read buffer       */
 
818
char    readbuf[MSG_SIZE];              /* Message read buffer       */
903
819
int     readoff = 0;                    /* Number of bytes in readbuf*/
904
 
BYTE    cmdline[CMD_SIZE+1];            /* Command line buffer       */
905
 
int     cmdoff = 0;                     /* Number of bytes in cmdline*/
906
 
TID     cmdtid;                         /* Command thread identifier */
907
 
TID     rctid;                          /* RC file thread identifier */
 
820
char    cmdline[CMD_SIZE+1];            /* Command line buffer       */
 
821
int     cmdoff = 0;                     /* Cursor position in cmdline*/
 
822
int     cmdlen = 0;                     /* Number of bytes in cmdline*/
908
823
BYTE    c;                              /* Character work area       */
909
824
FILE   *confp;                          /* Console file pointer      */
910
 
FILE   *logfp;                          /* Log file pointer          */
911
825
struct termios kbattr;                  /* Terminal I/O structure    */
912
826
size_t  kbbufsize = CMD_SIZE;           /* Size of keyboard buffer   */
913
 
BYTE   *kbbuf = NULL;                   /* Keyboard input buffer     */
 
827
char   *kbbuf = NULL;                   /* Keyboard input buffer     */
914
828
int     kblen;                          /* Number of chars in kbbuf  */
915
829
int     pipefd;                         /* Pipe file descriptor      */
916
830
int     keybfd;                         /* Keyboard file descriptor  */
918
832
fd_set  readset;                        /* Select file descriptors   */
919
833
struct  timeval tv;                     /* Select timeout structure  */
920
834
 
 
835
#if 1
 
836
    panel_compat_init();
 
837
    for (i=0; i < CMD_SIZE+1; i++)
 
838
      cmdline[i] = 0;
 
839
#endif
 
840
 
921
841
    /* Display thread started message on control panel */
922
842
    logmsg (_("HHCPN001I Control panel thread started: "
923
843
            "tid="TIDPAT", pid=%d\n"),
941
861
        return;
942
862
    }
943
863
 
944
 
    /* If stdout is not redirected, then write screen output
945
 
       to stdout and do not produce a log file.  If stdout is
946
 
       redirected, then write screen output to stderr and
947
 
       write the logfile to stdout */
948
 
    if (isatty(STDOUT_FILENO))
949
 
    {
950
 
        confp = stdout;
951
 
        logfp = NULL;
952
 
    }
953
 
    else
954
 
    {
955
 
        confp = stderr;
956
 
        logfp = stdout;
957
 
        /* Logfile should be unbuffered to be always in sync */
958
 
        setvbuf(logfp, NULL, _IONBF, 0);
959
 
    }
 
864
    /* Set up the input file descriptors */
 
865
    confp = stderr;
 
866
    pipefd = compat_msgpiper;
 
867
    keybfd = STDIN_FILENO;
 
868
 
 
869
    hdl_adsc(panel_cleanup, NULL);
960
870
 
961
871
    /* Set screen output stream to fully buffered */
962
872
    setvbuf (confp, NULL, _IOFBF, 0);
963
873
 
964
 
    /* Set up the input file descriptors */
965
 
    pipefd = sysblk.msgpiper;
966
 
    keybfd = STDIN_FILENO;
967
 
 
968
 
    /* Register the system cleanup exit routine */
969
 
    atexit (system_cleanup);
970
 
 
971
874
    /* Put the terminal into cbreak mode */
972
875
    tcgetattr (keybfd, &kbattr);
973
876
    kbattr.c_lflag &= ~(ECHO | ICANON);
975
878
    kbattr.c_cc[VTIME] = 0;
976
879
    tcsetattr (keybfd, TCSANOW, &kbattr);
977
880
 
978
 
#ifdef EXTERNALGUI
979
 
    if (!extgui)
980
 
#endif /*EXTERNALGUI*/
981
881
    /* Clear the screen */
982
882
    fprintf (confp,
983
883
            ANSI_WHT_BLK
984
884
            ANSI_ERASE_SCREEN);
985
885
 
986
 
#ifdef EXTERNALGUI
987
 
    if (!extgui)
988
 
    {
989
 
#endif /*EXTERNALGUI*/
990
886
    redraw_msgs = 1;
991
887
    redraw_cmd = 1;
992
 
#ifdef EXTERNALGUI
993
 
    }
994
 
#endif /*EXTERNALGUI*/
995
888
    redraw_status = 1;
996
889
 
997
 
    /* Wait for system to finish coming up */
998
 
    while (!initdone) sleep(1);
999
 
 
1000
 
    /* Start up the RC file processing thread */
1001
 
    create_thread(&rctid,&sysblk.detattr,process_rc_file,NULL);
1002
 
 
1003
890
    /* Process messages and commands */
1004
891
    while (1)
1005
892
    {
1006
893
        /* Set target CPU for commands and displays */
1007
 
        regs = sysblk.regs + sysblk.pcpu;
1008
 
        /* If the requested CPU is offline, then take the first available CPU*/
1009
 
        if(!regs->cpuonline)
1010
 
          /* regs = first online CPU
1011
 
           * sysblk.pcpu = number of online CPUs
1012
 
           */
1013
 
          for(regs = 0, sysblk.pcpu = 0, i = 0 ;
1014
 
              i < MAX_CPU_ENGINES ; ++i )
1015
 
            if (sysblk.regs[i].cpuonline) {
1016
 
              if (!regs)
1017
 
                regs = sysblk.regs + i;
1018
 
              ++sysblk.pcpu;
1019
 
            }
1020
 
 
1021
 
        if (!regs) regs = sysblk.regs;
 
894
        regs = sysblk.regs[sysblk.pcpu];
 
895
        if (!regs) regs = &sysblk.dummyregs;
1022
896
 
1023
897
#if defined(_FEATURE_SIE)
1024
898
        /* Point to SIE copy in SIE state */
1032
906
        FD_SET (pipefd, &readset);
1033
907
        maxfd = keybfd;
1034
908
        if (pipefd > maxfd) maxfd = pipefd;
1035
 
        maxfd = add_socket_devices_to_fd_set (&readset, maxfd);
1036
909
 
1037
910
        /* Wait for a message to arrive, a key to be pressed,
1038
911
           or the inactivity interval to expire */
1053
926
        if (FD_ISSET(keybfd, &readset))
1054
927
        {
1055
928
            /* Read character(s) from the keyboard */
1056
 
 
1057
929
            kblen = read (keybfd, kbbuf, kbbufsize-1);
 
930
 
1058
931
            if (kblen < 0)
1059
932
            {
1060
933
                fprintf (stderr,
1062
935
                        strerror(errno));
1063
936
                break;
1064
937
            }
 
938
 
1065
939
            kbbuf[kblen] = '\0';
1066
940
 
1067
941
            /* =NP= : Intercept NP commands & process */
1079
953
                        kbbuf[0] = '\0';
1080
954
                        redraw_status = 1;
1081
955
                    }
 
956
            cmdline[0] = '\0';
 
957
            cmdlen = 0;
 
958
            cmdoff = 0;
1082
959
                    switch(kbbuf[0]) {
1083
960
                        case 0x1b:                  /* ESC */
1084
961
                            NPDup = 0;
 
962
                cmdline[0] = '\0';
 
963
                cmdoff = 0;
 
964
                cmdlen = 0;
1085
965
                            break;
1086
966
                        case '?':
1087
967
                            NPhelpup = 1;
1089
969
                            break;
1090
970
                        case 'S':                   /* START */
1091
971
                        case 's':
1092
 
                            ASYNCHRONOUS_PANEL_CMD("start");
 
972
                            panel_command("start");
1093
973
                            break;
1094
974
                        case 'P':                   /* STOP */
1095
975
                        case 'p':
1096
 
                            ASYNCHRONOUS_PANEL_CMD("stop");
 
976
                            panel_command("stop");
1097
977
                            break;
1098
978
                        case 'T':                   /* RESTART */
1099
979
                        case 't':
1100
 
                            ASYNCHRONOUS_PANEL_CMD("restart");
 
980
                            panel_command("restart");
1101
981
                            break;
1102
982
                        case 'E':                   /* Ext int */
1103
983
                        case 'e':
1104
 
                            ASYNCHRONOUS_PANEL_CMD("ext");
 
984
                            panel_command("ext");
1105
985
                            redraw_status = 1;
1106
986
                            break;
1107
987
                        case 'O':                   /* Store */
1108
988
                        case 'o':
1109
 
                            NPaaddr = APPLY_PREFIXING (NPaddress, regs->PX);
 
989
                            NPaaddr = APPLY_PREFIXING ((U32)NPaddress, regs->PX);
1110
990
                            if (NPaaddr > regs->mainlim)
1111
991
                                break;
1112
992
                            regs->mainstor[NPaaddr] = 0;
1185
1065
                            sprintf(NPdevstr, "%x", NPdevaddr[i]);
1186
1066
                            strcpy(cmdline, "ipl ");
1187
1067
                            strcat(cmdline, NPdevstr);
1188
 
                            ASYNCHRONOUS_PANEL_CMD(cmdline);
 
1068
                            panel_command(cmdline);
1189
1069
                            strcpy(NPprompt2, "");
1190
1070
                            redraw_status = 1;
1191
1071
                            break;
1206
1086
                            sprintf(NPdevstr, "%x", NPdevaddr[i]);
1207
1087
                            strcpy(cmdline, "i ");
1208
1088
                            strcat(cmdline, NPdevstr);
1209
 
                            ASYNCHRONOUS_PANEL_CMD(cmdline);
 
1089
                            panel_command(cmdline);
1210
1090
                            strcpy(NPprompt2, "");
1211
1091
                            redraw_status = 1;
1212
1092
                            break;
1241
1121
                            strcpy(NPprompt1, "Confirm Powerdown Y or N");
1242
1122
                            redraw_status = 1;
1243
1123
                            break;
1244
 
                        case 4:                     /* IPL - 2nd part */
 
1124
                        case 4:                     /* POWER - 2nd part */
1245
1125
                            if (NPdevice == 'y' || NPdevice == 'Y')
1246
 
                                ASYNCHRONOUS_PANEL_CMD("quit");
 
1126
                            {
 
1127
                                panel_command("quit");
 
1128
                                while (1) sched_yield();
 
1129
                            }
1247
1130
                            strcpy(NPprompt1, "");
1248
1131
                            redraw_status = 1;
1249
1132
                            break;
1282
1165
                }
1283
1166
 
1284
1167
                /* Test for line up command */
1285
 
                if (strcmp(kbbuf+i, KBD_UP_ARROW) == 0)
 
1168
                if (strcmp(kbbuf+i, KBD_UP_ARROW) == 0
 
1169
                    || strcmp(kbbuf+i, xKBD_UP_ARROW) == 0)
1286
1170
                {
1287
 
                    if (firstmsgn == 0) break;
1288
 
                    firstmsgn--;
1289
 
                    redraw_msgs = 1;
 
1171
                    if (history_prev() != -1) {
 
1172
                        strcpy(cmdline, historyCmdLine);
 
1173
                        cmdoff = strlen(cmdline);
 
1174
                        cmdlen = cmdoff;
 
1175
                        NPDup = 0;
 
1176
                        NPDinit = 1;
 
1177
                        redraw_cmd = 1;
 
1178
                    }
1290
1179
                    break;
1291
1180
                }
1292
1181
 
1293
1182
                /* Test for line down command */
1294
 
                if (strcmp(kbbuf+i, KBD_DOWN_ARROW) == 0)
 
1183
                if (strcmp(kbbuf+i, KBD_DOWN_ARROW) == 0
 
1184
                    || strcmp(kbbuf+i, xKBD_DOWN_ARROW) == 0)
1295
1185
                {
1296
 
                    if (firstmsgn + NUM_LINES >= nummsgs) break;
1297
 
                    firstmsgn++;
1298
 
                    redraw_msgs = 1;
 
1186
                    if (history_next() != -1) {
 
1187
                        strcpy(cmdline, historyCmdLine);
 
1188
                        cmdoff = strlen(cmdline);
 
1189
                        cmdlen = cmdoff;
 
1190
                        NPDup = 0;
 
1191
                        NPDinit = 1;
 
1192
                        redraw_cmd = 1;
 
1193
                    }
1299
1194
                    break;
1300
1195
                }
1301
1196
 
1320
1215
                    break;
1321
1216
                }
1322
1217
 
 
1218
                /* Process backspace character  */
 
1219
                if (kbbuf[i] == '\b' || kbbuf[i] == '\x7F')
 
1220
                {
 
1221
                    if (cmdoff > 0) {
 
1222
                        int j;
 
1223
                        for (j = cmdoff-1; j<cmdlen; j++)
 
1224
                            cmdline[j] = cmdline[j+1];
 
1225
                        cmdoff--;
 
1226
                        cmdlen--;
 
1227
                    }
 
1228
                    i++;
 
1229
                    redraw_cmd = 1;
 
1230
                    break;
 
1231
                }
 
1232
                /* Process DEL character              */
 
1233
                if (strcmp(kbbuf+i, KBD_DELETE) == 0) {
 
1234
                    if (cmdoff < cmdlen) {
 
1235
                        int j;
 
1236
                        for (j = cmdoff; j<cmdlen; j++)
 
1237
                            cmdline[j] = cmdline[j+1];
 
1238
                        cmdlen--;
 
1239
                    }
 
1240
                    i++;
 
1241
                    redraw_cmd = 1;
 
1242
                    break;
 
1243
                }
 
1244
 
 
1245
                /* Process LEFT_ARROW character              */
 
1246
                if (strcmp(kbbuf+i, KBD_LEFT_ARROW) == 0
 
1247
                    || strcmp(kbbuf+i, xKBD_LEFT_ARROW) == 0)
 
1248
                {
 
1249
                    if (cmdoff > 0) cmdoff--;
 
1250
                    i++;
 
1251
                    redraw_cmd = 1;
 
1252
                    break;
 
1253
                }
 
1254
 
 
1255
                /* Test for other KBD_* strings           */
 
1256
                /* Just ignore them, no function assigned */
 
1257
                if (strcmp(kbbuf+i, KBD_RIGHT_ARROW) == 0
 
1258
                    || strcmp(kbbuf+i, xKBD_RIGHT_ARROW) == 0
 
1259
                    || strcmp(kbbuf+i, KBD_INSERT) == 0)
 
1260
                {
 
1261
                    redraw_msgs = 1;
 
1262
                    if (cmdoff < cmdlen)
 
1263
                        cmdoff++;
 
1264
                    break;
 
1265
                }
 
1266
 
1323
1267
                /* Process escape key */
1324
1268
                if (kbbuf[i] == '\x1B')
1325
1269
                {
1326
1270
                    /* =NP= : Switch to new panel display */
1327
1271
                    NP_init();
1328
1272
                    NPDup = 1;
 
1273
            cmdline[0] = '\0';
 
1274
            cmdoff = 0;
 
1275
            cmdlen = 0;
1329
1276
                    /* =END= */
1330
1277
                    break;
1331
1278
                }
1332
1279
 
1333
 
                /* Process backspace character */
1334
 
                if (kbbuf[i] == '\b' || kbbuf[i] == '\x7F'
1335
 
                    || strcmp(kbbuf+i, KBD_LEFT_ARROW) == 0)
 
1280
                /* Process TAB character              */
 
1281
                if (kbbuf[i] == '\t' || kbbuf[i] == '\x7F')
1336
1282
                {
1337
 
                    if (cmdoff > 0) cmdoff--;
1338
 
                    i++;
1339
 
                    redraw_cmd = 1;
1340
 
                    break;
 
1283
                   tab_pressed(cmdline, &cmdoff);
 
1284
                   cmdlen = strlen(cmdline);
 
1285
                   /* cmdoff = cmdlen;                */
 
1286
                   i++;
 
1287
                   redraw_cmd = 1;
 
1288
                   break;
1341
1289
                }
1342
1290
 
1343
1291
                /* Process the command if newline was read */
1344
1292
                if (kbbuf[i] == '\n')
1345
1293
                {
1346
 
                    cmdline[cmdoff] = '\0';
1347
 
                    /* =NP= create_thread replaced with: */
1348
 
                    if (NPDup == 0) {
1349
 
#ifdef EXTERNALGUI
1350
 
                        if (extgui && (cmdline[0] == ']'))
1351
 
                        {
1352
 
                            redraw_status = 1;
1353
 
 
1354
 
                            if (strncmp(cmdline,"]GREGS=",7) == 0)
1355
 
                            {
1356
 
                                gui_gregs = atoi(cmdline+7);
1357
 
                            }
1358
 
                            else
1359
 
                            if (strncmp(cmdline,"]CREGS=",7) == 0)
1360
 
                            {
1361
 
                                gui_cregs = atoi(cmdline+7);
1362
 
                            }
1363
 
                            else
1364
 
                            if (strncmp(cmdline,"]AREGS=",7) == 0)
1365
 
                            {
1366
 
                                gui_aregs = atoi(cmdline+7);
1367
 
                            }
1368
 
                            else
1369
 
                            if (strncmp(cmdline,"]FREGS=",7) == 0)
1370
 
                            {
1371
 
                                gui_fregs = atoi(cmdline+7);
1372
 
                            }
1373
 
                            else
1374
 
                            if (strncmp(cmdline,"]DEVLIST=",9) == 0)
1375
 
                            {
1376
 
                                gui_devlist = atoi(cmdline+9);
1377
 
                            }
1378
 
                            else
1379
 
                            if (strncmp(cmdline,"]MAINSTOR=",10) == 0)
1380
 
                            {
1381
 
                                fprintf(stderr,"MAINSTOR=%d\n",(U32)regs->mainstor);
1382
 
                                fprintf(stderr,"MAINSIZE=%d\n",(U32)sysblk.mainsize);
1383
 
                            }
1384
 
#if defined(OPTION_MIPS_COUNTING)
1385
 
                            else
1386
 
                            if (strncmp(cmdline,"]CPUPCT=",8) == 0)
1387
 
                            {
1388
 
                                gui_cpupct = atoi(cmdline+8);
1389
 
                            }
1390
 
#endif /*defined(OPTION_MIPS_COUNTING)*/
1391
 
                        }
1392
 
                        else
1393
 
#endif /*EXTERNALGUI*/
1394
 
                        {
1395
 
                            if ('#' == cmdline[0] || '*' == cmdline[0])
1396
 
                            {
 
1294
                    if (cmdlen == 0 && NPDup == 0) {
 
1295
                        history_show();
 
1296
                    } else {
 
1297
                        cmdline[cmdlen] = '\0';
 
1298
                        /* =NP= create_thread replaced with: */
 
1299
                        if (NPDup == 0) {
 
1300
                            if ('#' == cmdline[0] || '*' == cmdline[0]) {
1397
1301
                                if ('*' == cmdline[0])
1398
1302
                                    logmsg("%s\n", cmdline);
1399
 
                            }
1400
 
                            else
1401
 
                            {
1402
 
                                if (rc_thread_done)
1403
 
                                {
1404
 
                                    ASYNCHRONOUS_PANEL_CMD(cmdline);
1405
 
                                }
1406
 
                            }
1407
 
                        }
1408
 
                    } else {
1409
 
                        NPdataentry = 0;
1410
 
                        NPcurpos[0] = 24;
1411
 
                        NPcurpos[1] = 80;
1412
 
                        strcpy(NPcolor, "");
1413
 
                        switch (NPpending) {
1414
 
                            case 'r':
1415
 
                                sscanf(cmdline, "%x", &NPaddress);
1416
 
                                NPcuraddr = -1;
1417
 
                                strcpy(NPprompt1, "");
1418
 
                                break;
1419
 
                            case 'd':
1420
 
                                sscanf(cmdline, "%x", &NPdata);
1421
 
                                NPcurdata = -1;
1422
 
                                strcpy(NPprompt1, "");
1423
 
                                break;
1424
 
                            case 'n':
1425
 
                                if (strlen(cmdline) < 1) {
1426
 
                                    strcpy(cmdline, NPdevname[NPasgn]);
1427
 
                                }
1428
 
                                strcpy(NPdevname[NPasgn], "");
1429
 
                                strcpy(NPentered, "devinit ");
1430
 
                                sprintf(NPdevstr, "%x", NPdevaddr[NPasgn]);
1431
 
                                strcat(NPentered, NPdevstr);
1432
 
                                strcat(NPentered, " ");
1433
 
                                strcat(NPentered, cmdline);
1434
 
                                ASYNCHRONOUS_PANEL_CMD(NPentered);
1435
 
                                strcpy(NPprompt2, "");
1436
 
                                break;
1437
 
                            default:
1438
 
                                break;
1439
 
                        }
1440
 
                        redraw_status = 1;
 
1303
                            } else {
 
1304
                                history_requested = 0;
 
1305
                                panel_command(cmdline);
 
1306
                                cmdoff = 0;
 
1307
                                for (;cmdlen >=0; cmdlen--)
 
1308
                                    cmdline[cmdlen] = '\0';
 
1309
                                cmdlen = 0;
 
1310
                                if (history_requested == 1) {
 
1311
                                    strcpy(cmdline, historyCmdLine);
 
1312
                                    cmdoff = strlen(cmdline);
 
1313
                                    cmdlen = cmdoff;
 
1314
                                    NPDup = 0;
 
1315
                                    NPDinit = 1;
 
1316
                                    redraw_cmd = 1;
 
1317
                                }
 
1318
                            }
 
1319
                        } else {
 
1320
                            NPdataentry = 0;
 
1321
                            NPcurpos[0] = 24;
 
1322
                            NPcurpos[1] = 80;
 
1323
                            strcpy(NPcolor, "");
 
1324
                            switch (NPpending) {
 
1325
                                case 'r':
 
1326
                                    sscanf(cmdline, "%x", &NPaddress);
 
1327
                                    NPcuraddr = -1;
 
1328
                                    strcpy(NPprompt1, "");
 
1329
                                    break;
 
1330
                                case 'd':
 
1331
                                    sscanf(cmdline, "%x", &NPdata);
 
1332
                                    NPcurdata = -1;
 
1333
                                    strcpy(NPprompt1, "");
 
1334
                                    break;
 
1335
                                case 'n':
 
1336
                                    if (strlen(cmdline) < 1) {
 
1337
                                        strcpy(cmdline, NPdevname[NPasgn]);
 
1338
                                    }
 
1339
                                    strcpy(NPdevname[NPasgn], "");
 
1340
                                    strcpy(NPentered, "devinit ");
 
1341
                                    sprintf(NPdevstr, "%x", NPdevaddr[NPasgn]);
 
1342
                                    strcat(NPentered, NPdevstr);
 
1343
                                    strcat(NPentered, " ");
 
1344
                                    strcat(NPentered, cmdline);
 
1345
                                    panel_command(NPentered);
 
1346
                                    strcpy(NPprompt2, "");
 
1347
                                    break;
 
1348
                                default:
 
1349
                                    break;
 
1350
                            }
 
1351
                            redraw_status = 1;
 
1352
                cmdline[0] = '\0';
 
1353
                cmdlen = 0;
 
1354
                cmdoff = 0;
 
1355
                        }
 
1356
                        /* =END= */
 
1357
                        redraw_cmd = 1;
1441
1358
                    }
1442
 
                    /* =END= */
1443
 
                    cmdoff = 0;
1444
 
#ifdef EXTERNALGUI
1445
 
                    /* Process *ALL* of the 'keyboard' (stdin) buffer data! */
1446
 
                    if (extgui) {i++; continue;}
1447
 
#endif /*EXTERNALGUI*/
1448
 
                    redraw_cmd = 1;
1449
1359
                    break;
1450
1360
                }
1451
1361
 
1458
1368
                }
1459
1369
 
1460
1370
                /* Append the character to the command buffer */
1461
 
                if (cmdoff < CMD_SIZE-1) cmdline[cmdoff++] = kbbuf[i];
 
1371
                if (cmdoff < CMD_SIZE-1) {
 
1372
                    if (cmdoff < cmdlen) {
 
1373
                        int j;
 
1374
                        for (j=cmdlen-1; j>=cmdoff; j--)
 
1375
                            cmdline[j+1] = cmdline[j];
 
1376
                        cmdline[cmdoff++] = kbbuf[i];
 
1377
                    }
 
1378
                    else
 
1379
                        cmdline[cmdoff++] = kbbuf[i];
 
1380
                    cmdlen++;
 
1381
                }
1462
1382
                i++;
1463
1383
                redraw_cmd = 1;
1464
 
 
1465
1384
            } /* end for(i) */
1466
1385
        }
1467
1386
 
1468
1387
        /* If a message has arrived then receive it */
1469
1388
        if (FD_ISSET(pipefd, &readset))
1470
1389
        {
1471
 
            /* Clear the message buffer */
1472
 
            memset (readbuf, SPACE, MSG_SIZE);
1473
 
 
1474
 
            /* Read message bytes until newline */
1475
 
            while (1)
1476
 
            {
1477
 
                /* Read a byte from the message pipe */
1478
 
                rc = read (pipefd, &c, 1);
1479
 
                if (rc < 1)
1480
 
                {
1481
 
                    fprintf (stderr,
1482
 
                            "HHCPN006E message pipe read: %s\n",
1483
 
                            strerror(errno));
1484
 
                    break;
1485
 
                }
1486
 
 
1487
 
 
1488
 
                /* Exit if newline was read */
1489
 
                if (c == '\n') break;
1490
 
 
1491
 
                /* Handle tab character */
1492
 
                if (c == '\t')
1493
 
                {
1494
 
                    readoff += 8;
1495
 
                    readoff &= 0xFFFFFFF8;
1496
 
                    continue;
1497
 
                }
1498
 
 
1499
 
                /* Eliminate non-printable characters */
1500
 
                if (!isprint(c)) c = SPACE;
1501
 
 
1502
 
                /* Append the byte to the read buffer */
1503
 
                if (readoff < MSG_SIZE) readbuf[readoff++] = c;
1504
 
 
1505
 
            } /* end while */
1506
 
 
1507
 
            /* Exit if read was unsuccessful */
1508
 
            if (rc < 1) break;
1509
 
 
1510
 
            /* Copy the message to the log file if present */
1511
 
            if (logfp != NULL)
1512
 
            {
1513
 
                fprintf (logfp, "%.*s\n", readoff, readbuf);
1514
 
                if (ferror(logfp))
1515
 
                {
1516
 
                    fclose (logfp);
1517
 
                    logfp = NULL;
1518
 
                }
1519
 
            }
1520
 
 
1521
 
            /* Copy message to circular buffer and empty read buffer */
1522
 
#if defined(EXTERNALGUI) && !defined(OPTION_HTTP_SERVER)
1523
 
            if (!extgui)
1524
 
#endif /*EXTERNALGUI*/
1525
 
            memcpy (msgbuf + (msgslot * MSG_SIZE), readbuf, MSG_SIZE);
1526
 
            readoff = 0;
1527
 
 
1528
 
#if defined(EXTERNALGUI) && !defined(OPTION_HTTP_SERVER)
1529
 
            if (!extgui)
1530
 
            {
1531
 
#endif /*EXTERNALGUI*/
1532
 
            /* Update message count and next available slot number */
1533
 
            if (nummsgs < MAX_MSGS)
1534
 
                msgslot = ++nummsgs;
1535
 
            else
1536
 
                msgslot++;
1537
 
            if (msgslot == MAX_MSGS) msgslot = 0;
1538
 
 
1539
 
            /* Calculate the first line to display */
1540
 
            firstmsgn = nummsgs - NUM_LINES;
1541
 
            if (firstmsgn < 0) firstmsgn = 0;
1542
 
 
1543
 
            /* Set the display update indicator */
1544
 
            redraw_msgs = 1;
1545
 
#if defined(EXTERNALGUI) && !defined(OPTION_HTTP_SERVER)
1546
 
            }
1547
 
#endif /*EXTERNALGUI*/
1548
 
        }
1549
 
 
1550
 
        /* Check if any sockets have received new connections */
1551
 
        check_socket_devices_for_connections (&readset);
1552
 
 
1553
 
#ifdef EXTERNALGUI
1554
 
        if (!extgui)
1555
 
#endif /*EXTERNALGUI*/
 
1390
            /* Read message bytes until newline... */
 
1391
            c = 0;
 
1392
            while (c != '\n' && c != '\r')
 
1393
            {
 
1394
                /* Initialize the read buffer */
 
1395
                if (!readoff || readoff >= MSG_SIZE) {
 
1396
                    memset (readbuf, SPACE, MSG_SIZE);
 
1397
                    readoff = 0;
 
1398
                }
 
1399
 
 
1400
                /* Read message bytes and copy into read buffer
 
1401
                   until we either encounter a newline character
 
1402
                   or our buffer is completely filled with data. */
 
1403
                while (c != '\n' && c != '\r')
 
1404
                {
 
1405
                    /* Read a byte from the message pipe */
 
1406
                    rc = read (pipefd, &c, 1);
 
1407
                    if (rc < 1) {
 
1408
                        fprintf (stderr,
 
1409
                                _("HHCPN006E message pipe read: %s\n"),
 
1410
                                strerror(errno));
 
1411
                        break;
 
1412
                    }
 
1413
 
 
1414
                    /* Break to process received message
 
1415
                       whenever a newline is encountered */
 
1416
                    if (c == '\n' || c == '\r') {
 
1417
                        readoff = 0;    /* (for next time) */
 
1418
                        break;
 
1419
                    }
 
1420
 
 
1421
                    /* Handle tab character */
 
1422
                    if (c == '\t') {
 
1423
                        readoff += 8;
 
1424
                        readoff &= 0xFFFFFFF8;
 
1425
                        /* Messages longer than one screen line will
 
1426
                           be continued on the very next screen line */
 
1427
                        if (readoff >= MSG_SIZE)
 
1428
                            break;
 
1429
                        else continue;
 
1430
                    }
 
1431
 
 
1432
                    /* Eliminate non-displayable characters */
 
1433
                    if (!isgraph(c)) c = SPACE;
 
1434
 
 
1435
                    /* Stuff byte into message processing buffer */
 
1436
                    readbuf[readoff++] = c;
 
1437
 
 
1438
                    /* Messages longer than one screen line will
 
1439
                       be continued on the very next screen line */
 
1440
                    if (readoff >= MSG_SIZE)
 
1441
                        break;
 
1442
                }
 
1443
 
 
1444
                /* If we have a message to be displayed (or a complete
 
1445
                   part of one), then copy it to the circular buffer. */
 
1446
                if (!readoff || readoff >= MSG_SIZE) {
 
1447
                    /* Set the display update indicator */
 
1448
                    redraw_msgs = 1;
 
1449
 
 
1450
                    memcpy(msgbuf+(msgslot*MSG_SIZE),readbuf,MSG_SIZE);
 
1451
 
 
1452
                    /* Update message count and next available slot */
 
1453
                    if (nummsgs < MAX_MSGS)
 
1454
                        msgslot = ++nummsgs;
 
1455
                    else
 
1456
                        msgslot++;
 
1457
                    if (msgslot >= MAX_MSGS) msgslot = 0;
 
1458
 
 
1459
                    /* Calculate the first line to display */
 
1460
                    firstmsgn = nummsgs - NUM_LINES;
 
1461
                    if (firstmsgn < 0) firstmsgn = 0;
 
1462
                }
 
1463
                if (rc < 1) break; /* Exit if read was unsuccessful */
 
1464
            } /* end while read(pipefd) */
 
1465
            if (rc < 1) break; /* Exit if read was unsuccessful */
 
1466
        } /* end if (FD_ISSET(pipefd)) */
 
1467
 
1556
1468
        /* =NP= : Reinit traditional panel if NP is down */
1557
1469
        if (NPDup == 0 && NPDinit == 1) {
1558
1470
            NPDinit = 0;
1566
1478
 
1567
1479
        /* Obtain the PSW for target CPU */
1568
1480
        memset (curpsw, 0x00, sizeof(curpsw));
1569
 
        store_psw (regs, curpsw);
 
1481
        copy_psw (regs, curpsw);
1570
1482
 
1571
1483
        /* Isolate the PSW interruption wait bit */
1572
1484
        pswwait = curpsw[1] & 0x02;
1576
1488
           the CPU stopped state has changed */
1577
1489
        if (memcmp(curpsw, prvpsw, sizeof(curpsw)) != 0 || (
1578
1490
#if defined(_FEATURE_SIE)
1579
 
                  regs->sie_state ?  regs->hostregs->instcount :
 
1491
                  SIE_MODE(regs) ?  regs->hostregs->instcount :
1580
1492
#endif /*defined(_FEATURE_SIE)*/
1581
1493
                  regs->instcount) != prvicount
 
1494
#if defined(OPTION_SHARED_DEVICES)
 
1495
            || sysblk.shrdcount != prvscount
 
1496
#endif
1582
1497
            || regs->cpustate != prvstate)
1583
1498
        {
1584
1499
            redraw_status = 1;
1585
1500
            memcpy (prvpsw, curpsw, sizeof(prvpsw));
1586
1501
            prvicount =
1587
1502
#if defined(_FEATURE_SIE)
1588
 
                        regs->sie_state ? regs->hostregs->instcount :
 
1503
                        SIE_MODE(regs) ? regs->hostregs->instcount :
1589
1504
#endif /*defined(_FEATURE_SIE)*/
1590
1505
                        regs->instcount;
1591
1506
            prvstate = regs->cpustate;
 
1507
#if defined(OPTION_SHARED_DEVICES)
 
1508
            prvscount = sysblk.shrdcount;
 
1509
#endif
1592
1510
        }
1593
1511
 
1594
1512
        /* =NP= : Display the screen - traditional or NP */
1598
1516
        /*        the NP display as an else after those ifs */
1599
1517
 
1600
1518
        if (NPDup == 0) {
1601
 
#ifdef EXTERNALGUI
1602
 
            if (!extgui)
1603
 
#endif /*EXTERNALGUI*/
1604
1519
            /* Rewrite the screen if display update indicators are set */
1605
1520
            if (redraw_msgs && !sysblk.npquiet)
1606
1521
            {
1626
1541
 
1627
1542
            if (redraw_status && !sysblk.npquiet)
1628
1543
            {
 
1544
                if(IS_CPU_ONLINE(sysblk.pcpu))
1629
1545
                /* Display the PSW and instruction counter for CPU 0 */
1630
1546
                fprintf (confp,
1631
1547
                    "%s"
1632
 
#if MAX_CPU_ENGINES > 1
1633
1548
                    "CPU%4.4X "
1634
 
#endif
1635
1549
                    "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X"
1636
1550
                       " %2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X"
1637
1551
                    " %c%c%c%c%c%c%c%c instcount=%llu"
1638
1552
                    "%s",
1639
 
#ifdef EXTERNALGUI
1640
 
                    extgui ? ("STATUS=") :
1641
 
#endif /*EXTERNALGUI*/
1642
1553
                    (ANSI_ROW24_COL1 ANSI_YELLOW_RED),
1643
 
#if MAX_CPU_ENGINES > 1
1644
1554
                    regs->cpuad,
1645
 
#endif
1646
1555
                    curpsw[0], curpsw[1], curpsw[2], curpsw[3],
1647
1556
                    curpsw[4], curpsw[5], curpsw[6], curpsw[7],
1648
1557
                    curpsw[8], curpsw[9], curpsw[10], curpsw[11],
1652
1561
                    pswwait ? 'W' : '.',
1653
1562
                    regs->loadstate ? 'L' : '.',
1654
1563
                    regs->checkstop ? 'C' : '.',
1655
 
                    regs->psw.prob ? 'P' : '.',
 
1564
                    PROBSTATE(&regs->psw) ? 'P' : '.',
1656
1565
#if defined(_FEATURE_SIE)
1657
 
                    regs->sie_state ? 'S' : '.',
 
1566
                    SIE_MODE(regs) ? 'S' : '.',
1658
1567
#else /*!defined(_FEATURE_SIE)*/
1659
1568
                    '.',
1660
1569
#endif /*!defined(_FEATURE_SIE)*/
1664
1573
                    ' ',
1665
1574
#endif
1666
1575
#if defined(_FEATURE_SIE)
1667
 
                    regs->sie_state ?  (long long) regs->hostregs->instcount :
 
1576
                    SIE_MODE(regs) ?  (long long) regs->hostregs->instcount :
1668
1577
#endif /*defined(_FEATURE_SIE)*/
1669
1578
                    (long long)regs->instcount,
1670
 
#ifdef EXTERNALGUI
1671
 
                    extgui ? "\n" :
1672
 
#endif /*EXTERNALGUI*/
1673
1579
                    ANSI_ERASE_EOL);
1674
 
 
1675
 
#ifdef EXTERNALGUI
1676
 
                if (extgui)
1677
 
                {
1678
 
                    /* SYS / WAIT lights */
1679
 
                    if (!(regs->cpustate == CPUSTATE_STOPPING ||
1680
 
                        regs->cpustate == CPUSTATE_STOPPED))
1681
 
                        fprintf(confp,"SYS=%c\n",pswwait?'0':'1');
1682
 
#ifdef OPTION_MIPS_COUNTING
1683
 
                    /* Calculate MIPS rate */
1684
 
#ifdef FEATURE_CPU_RECONFIG
1685
 
                    for (mipsrate = siosrate = i = 0; i < MAX_CPU_ENGINES; i++)
1686
 
                        if(sysblk.regs[i].cpuonline)
1687
 
#else /*!FEATURE_CPU_RECONFIG*/
1688
 
                        for(mipsrate = siosrate = i = 0; i < sysblk.numcpu; i++)
1689
 
#endif /*!FEATURE_CPU_RECONFIG*/
1690
 
                        {
1691
 
                            mipsrate += sysblk.regs[i].mipsrate;
1692
 
                            siosrate += sysblk.regs[i].siosrate;
1693
 
                        }
1694
 
 
1695
 
                    if (mipsrate > 100000) mipsrate = 0;        /* ignore wildly high rate */
1696
 
 
1697
 
                    /* MIPS rate */
1698
 
                    if (prevmipsrate != mipsrate)
1699
 
                    {
1700
 
                        prevmipsrate = mipsrate;
1701
 
                        fprintf(confp, "MIPS=%2.1d.%2.2d\n",
1702
 
                            prevmipsrate / 1000, (prevmipsrate % 1000) / 10);
1703
 
                    }
1704
 
 
1705
 
                    /* SIO rate */
1706
 
                    if (prevsiosrate != siosrate)
1707
 
                    {
1708
 
                        prevsiosrate = siosrate;
1709
 
                        fprintf(confp, "SIOS=%5d\n",prevsiosrate);
1710
 
                    }
1711
 
 
1712
 
#endif /*OPTION_MIPS_COUNTING*/
1713
 
                    if (gui_gregs)  /* GP regs */
1714
 
                    {
1715
 
                        fprintf(confp,"GR0-3=%8.8X %8.8X %8.8X %8.8X\n",
1716
 
                            regs->GR_L(0),regs->GR_L(1),regs->GR_L(2),regs->GR_L(3));
1717
 
                        fprintf(confp,"GR4-7=%8.8X %8.8X %8.8X %8.8X\n",
1718
 
                            regs->GR_L(4),regs->GR_L(5),regs->GR_L(6),regs->GR_L(7));
1719
 
                        fprintf(confp,"GR8-B=%8.8X %8.8X %8.8X %8.8X\n",
1720
 
                            regs->GR_L(8),regs->GR_L(9),regs->GR_L(10),regs->GR_L(11));
1721
 
                        fprintf(confp,"GRC-F=%8.8X %8.8X %8.8X %8.8X\n",
1722
 
                            regs->GR_L(12),regs->GR_L(13),regs->GR_L(14),regs->GR_L(15));
1723
 
                    }
1724
 
 
1725
 
                    if (gui_cregs)  /* CR regs */
1726
 
                    {
1727
 
                        fprintf(confp,"CR0-3=%8.8X %8.8X %8.8X %8.8X\n",
1728
 
                            regs->CR_L(0),regs->CR_L(1),regs->CR_L(2),regs->CR_L(3));
1729
 
                        fprintf(confp,"CR4-7=%8.8X %8.8X %8.8X %8.8X\n",
1730
 
                            regs->CR_L(4),regs->CR_L(5),regs->CR_L(6),regs->CR_L(7));
1731
 
                        fprintf(confp,"CR8-B=%8.8X %8.8X %8.8X %8.8X\n",
1732
 
                            regs->CR_L(8),regs->CR_L(9),regs->CR_L(10),regs->CR_L(11));
1733
 
                        fprintf(confp,"CRC-F=%8.8X %8.8X %8.8X %8.8X\n",
1734
 
                            regs->CR_L(12),regs->CR_L(13),regs->CR_L(14),regs->CR_L(15));
1735
 
                    }
1736
 
 
1737
 
                    if (gui_aregs)  /* AR regs */
1738
 
                    {
1739
 
                        fprintf(confp,"AR0-3=%8.8X %8.8X %8.8X %8.8X\n",
1740
 
                            regs->AR(0),regs->AR(1),regs->AR(2),regs->AR(3));
1741
 
                        fprintf(confp,"AR4-7=%8.8X %8.8X %8.8X %8.8X\n",
1742
 
                            regs->AR(4),regs->AR(5),regs->AR(6),regs->AR(7));
1743
 
                        fprintf(confp,"AR8-B=%8.8X %8.8X %8.8X %8.8X\n",
1744
 
                            regs->AR(8),regs->AR(9),regs->AR(10),regs->AR(11));
1745
 
                        fprintf(confp,"ARC-F=%8.8X %8.8X %8.8X %8.8X\n",
1746
 
                            regs->AR(12),regs->AR(13),regs->AR(14),regs->AR(15));
1747
 
                    }
1748
 
 
1749
 
                    if (gui_fregs)  /* FP regs */
1750
 
                    {
1751
 
                        fprintf(confp,"FR0-2=%8.8X %8.8X %8.8X %8.8X\n",
1752
 
                            regs->fpr[0],regs->fpr[1],regs->fpr[2],regs->fpr[3]);
1753
 
                        fprintf(confp,"FR4-6=%8.8X %8.8X %8.8X %8.8X\n",
1754
 
                            regs->fpr[4],regs->fpr[5],regs->fpr[6],regs->fpr[7]);
1755
 
                    }
1756
 
 
1757
 
#if defined(OPTION_MIPS_COUNTING)
1758
 
                    if (gui_cpupct)  /* CPU Utilization */
1759
 
                        fprintf(confp,"CPUPCT=%d\n",(int)(100.0 * regs->cpupct));
1760
 
#endif /*defined(OPTION_MIPS_COUNTING)*/
1761
 
 
1762
 
                    if (gui_devlist)  /* device status */
1763
 
                        gui_devlist_status (confp);
1764
 
                }
1765
 
#endif /*EXTERNALGUI*/
 
1580
                else
 
1581
                fprintf (confp,
 
1582
                    ANSI_ROW24_COL1 ANSI_YELLOW_RED
 
1583
                    "CPU%4.4X Offline"
 
1584
                    ANSI_ERASE_EOL,
 
1585
                    regs->cpuad);
1766
1586
            } /* end if(redraw_status) */
1767
 
#ifdef EXTERNALGUI
1768
 
                        else /* !redraw_status */
1769
 
                        {
1770
 
                    /* If we're under the control of an external GUI,
1771
 
                       some status info we need to send ALL the time. */
1772
 
                    if (extgui)
1773
 
                                {
1774
 
                    /* SYS / WAIT lights */
1775
 
                    if (!(regs->cpustate == CPUSTATE_STOPPING ||
1776
 
                        regs->cpustate == CPUSTATE_STOPPED))
1777
 
                        fprintf(confp,"SYS=%c\n",pswwait?'0':'1');
1778
 
 
1779
 
#if defined(OPTION_MIPS_COUNTING)
1780
 
                    if (gui_cpupct)  /* CPU Utilization */
1781
 
                        fprintf(confp,"CPUPCT=%d\n",(int)(100.0 * regs->cpupct));
1782
 
#endif /*defined(OPTION_MIPS_COUNTING)*/
1783
 
 
1784
 
                    if (gui_devlist)  /* device status */
1785
 
                        gui_devlist_status (confp);
1786
 
                                }
1787
 
                        }
1788
 
 
1789
 
            if (!extgui)
1790
 
#endif /*EXTERNALGUI*/
 
1587
 
1791
1588
            if (redraw_cmd)
1792
1589
            {
1793
1590
                /* Display the command line */
1798
1595
                    "Command ==> "
1799
1596
                    ANSI_WHITE_BLACK);
1800
1597
 
1801
 
                for (i = 0; i < cmdoff; i++)
 
1598
                for (i = 0; i < cmdlen; i++)
1802
1599
                    putc (cmdline[i], confp);
1803
1600
 
1804
1601
                fprintf (confp,
1809
1606
            /* Flush screen buffer and reset display update indicators */
1810
1607
            if (redraw_msgs || redraw_cmd || redraw_status)
1811
1608
            {
1812
 
#ifdef EXTERNALGUI
1813
 
                if (!extgui)
1814
 
#endif /*EXTERNALGUI*/
1815
1609
                fprintf (confp,
1816
1610
                    ANSI_POSITION_CURSOR,
1817
1611
                    23, 13+cmdoff);
1827
1621
                   || (redraw_cmd && NPdataentry == 1)) {
1828
1622
                if (NPDinit == 0) {
1829
1623
                    NPDinit = 1;
1830
 
#ifdef EXTERNALGUI
1831
 
                    if (!extgui)
1832
 
#endif /*EXTERNALGUI*/
1833
1624
                    NP_screen(confp);
1834
1625
                }
1835
 
#ifdef EXTERNALGUI
1836
 
                if (!extgui)
1837
 
#endif /*EXTERNALGUI*/
1838
 
                NP_update(confp, cmdline, cmdoff);
 
1626
                NP_update(confp, cmdline, cmdlen);
1839
1627
                fflush (confp);
1840
1628
                redraw_msgs = 0;
1841
1629
                redraw_cmd = 0;
1850
1638
    return;
1851
1639
 
1852
1640
} /* end function panel_display */
1853
 
 
1854
 
#if defined(EXTERNALGUI)
1855
 
 
1856
 
void gui_devlist_status (FILE *confp)
1857
 
{
1858
 
    DEVBLK *dev;
1859
 
 
1860
 
    for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
1861
 
    {
1862
 
        if (!(dev->pmcw.flag5 & PMCW5_V)) continue;
1863
 
 
1864
 
        stat_online = stat_busy = stat_pend = stat_open = 0;
1865
 
 
1866
 
        (dev->hnd->query)(dev, &devclass, sizeof(devnam), devnam);
1867
 
 
1868
 
        devnam[255] = 0;   /* (ensure null termination) */
1869
 
 
1870
 
        if ((dev->console && dev->connected) ||
1871
 
            (strlen(dev->filename) > 0))
1872
 
            stat_online = 1;
1873
 
        if (dev->busy) stat_busy = 1;
1874
 
        if (dev->pending) stat_pend = 1;
1875
 
        if (dev->fd > 2) stat_open = 1;
1876
 
 
1877
 
        fprintf(confp, "DEV=%4.4X %4.4X %-4.4s %d%d%d%d %s\n",
1878
 
            dev->devnum,
1879
 
            dev->devtype,
1880
 
            devclass,
1881
 
            stat_online,
1882
 
            stat_busy,
1883
 
            stat_pend,
1884
 
            stat_open,
1885
 
            devnam);
1886
 
    }
1887
 
 
1888
 
    fprintf(confp, "DEV=X\n");    /* (indicate end of list) */
1889
 
}
1890
 
 
1891
 
#endif /*defined(EXTERNALGUI)*/
1892
 
 
1893
 
 
1894
 
/*===================================================================*/
1895
 
/*              S o c k e t  D e v i c e s ...                       */
1896
 
/*===================================================================*/
1897
 
 
1898
 
// #define DEBUG_SOCKDEV
1899
 
 
1900
 
#ifdef DEBUG_SOCKDEV
1901
 
    #define logdebug(args...) logmsg(## args)
1902
 
#else
1903
 
    #define logdebug(args...) do {} while (0)
1904
 
#endif /* DEBUG_SOCKDEV */
1905
 
 
1906
 
/* Linked list of bind structures for bound socket devices */
1907
 
 
1908
 
LIST_ENTRY  bind_head;      /* (bind_struct list anchor) */
1909
 
LOCK        bind_lock;      /* (lock for accessing list) */
1910
 
 
1911
 
/*-------------------------------------------------------------------*/
1912
 
/* bind_device   bind a device to a socket (adds entry to our list   */
1913
 
/*               of bound devices) (1=success, 0=failure)            */
1914
 
/*-------------------------------------------------------------------*/
1915
 
int bind_device (DEVBLK* dev, char* spec)
1916
 
{
1917
 
    bind_struct* bs;
1918
 
 
1919
 
    logdebug("bind_device (%4.4X, %s)\n", dev->devnum, spec);
1920
 
 
1921
 
    /* Error if device already bound */
1922
 
 
1923
 
    if (dev->bs)
1924
 
    {
1925
 
        logmsg (_("HHCSD001E Device %4.4X already bound to socket %s\n"),
1926
 
            dev->devnum, dev->bs->spec);
1927
 
        return 0;   /* (failure) */
1928
 
    }
1929
 
 
1930
 
    /* Create a new bind_struct entry */
1931
 
 
1932
 
    bs = malloc(sizeof(bind_struct));
1933
 
 
1934
 
    if (!bs)
1935
 
    {
1936
 
        logmsg (_("HHCSD002E bind_device malloc() failed for device %4.4X\n"),
1937
 
            dev->devnum);
1938
 
        return 0;   /* (failure) */
1939
 
    }
1940
 
 
1941
 
    memset(bs,0,sizeof(bind_struct));
1942
 
 
1943
 
    if (!(bs->spec = safe_strdup(spec)))
1944
 
    {
1945
 
        logmsg (_("HHCSD003E bind_device safe_strdup() failed for device %4.4X\n"),
1946
 
            dev->devnum);
1947
 
        free (bs);
1948
 
        return 0;   /* (failure) */
1949
 
    }
1950
 
 
1951
 
    /* Create a listening socket */
1952
 
 
1953
 
    if (bs->spec[0] == '/') bs->sd = unix_socket (bs->spec);
1954
 
    else                    bs->sd = inet_socket (bs->spec);
1955
 
 
1956
 
    if (bs->sd == -1)
1957
 
    {
1958
 
        /* (error message already issued) */
1959
 
        free (bs);
1960
 
        return 0; /* (failure) */
1961
 
    }
1962
 
 
1963
 
    /* Chain device and socket to each other */
1964
 
 
1965
 
    dev->bs = bs;
1966
 
    bs->dev = dev;
1967
 
 
1968
 
    /* Add the new entry to our list of bound devices */
1969
 
 
1970
 
    obtain_lock(&bind_lock);
1971
 
    InsertListTail(&bind_head,&bs->bind_link);
1972
 
    release_lock(&bind_lock);
1973
 
 
1974
 
    logmsg (_("HHCSD004I Device %4.4X bound to socket %s\n"),
1975
 
        dev->devnum, dev->bs->spec);
1976
 
 
1977
 
    return 1;   /* (success) */
1978
 
}
1979
 
 
1980
 
/*-------------------------------------------------------------------*/
1981
 
/* unbind_device   unbind a device from a socket (removes entry from */
1982
 
/*                 our list and discards it) (1=success, 0=failure)  */
1983
 
/*-------------------------------------------------------------------*/
1984
 
int unbind_device (DEVBLK* dev)
1985
 
{
1986
 
    bind_struct* bs;
1987
 
 
1988
 
    logdebug("unbind_device(%4.4X)\n", dev->devnum);
1989
 
 
1990
 
    /* Error if device not bound */
1991
 
 
1992
 
    if (!(bs = dev->bs))
1993
 
    {
1994
 
        logmsg (_("HHCSD005E Device %4.4X not bound to any socket\n"),
1995
 
            dev->devnum);
1996
 
        return 0;   /* (failure) */
1997
 
    }
1998
 
 
1999
 
    /* Error if someone still connected */
2000
 
 
2001
 
    if (dev->fd != -1)
2002
 
    {
2003
 
        logmsg (_("HHCSD006E Client %s (%s) still connected to device %4.4X (%s)\n"),
2004
 
            dev->bs->clientip, dev->bs->clientname, dev->devnum, dev->bs->spec);
2005
 
        return 0;   /* (failure) */
2006
 
    }
2007
 
 
2008
 
    /* IMPORTANT! it's bad form to close a listening socket (and it
2009
 
     * happens to crash the Cygwin build) while another thread is still
2010
 
     * listening for connections on that socket (i.e. is in its FD_SET
2011
 
     * 'select' list). Thus we always issue a message (any message)
2012
 
     * immediately AFTER removing the entry from the sockdev (bind_struct)
2013
 
     * list and BEFORE closing our listening socket, thereby forcing
2014
 
     * the panel thread to rebuild its FD_SET 'select' list. (It wakes up
2015
 
     * from its 'select' as a result of our sending it our message and
2016
 
     * then before issuing another 'select' before going back to sleep,
2017
 
     * it then rebuilds its FD_SET 'select' list based on the current
2018
 
     * state of the sockdev (bind_struct) list, and since we just removed
2019
 
     * our entry from that list, the panel thread will thus not add our
2020
 
     * listening socket to its FD_SET 'select' list and thus we can then
2021
 
     * SAFELY close the listening socket).
2022
 
     */
2023
 
 
2024
 
    /* Remove the entry from our list */
2025
 
 
2026
 
    obtain_lock(&bind_lock);
2027
 
    RemoveListEntry(&bs->bind_link);
2028
 
    release_lock(&bind_lock);
2029
 
 
2030
 
    /* Issue message to wake up panel thread from its 'select' */
2031
 
 
2032
 
    logmsg (_("HHCSD007I Device %4.4X unbound from socket %s\n"),
2033
 
        dev->devnum, bs->spec);
2034
 
 
2035
 
    /* Give panel thread time to process our message
2036
 
     * and rebuild its select list. */
2037
 
 
2038
 
    usleep(100000);
2039
 
 
2040
 
    /* Now safe to close the listening socket */
2041
 
 
2042
 
    if (bs->sd != -1)
2043
 
        close (bs->sd);
2044
 
 
2045
 
    /* Unchain device and socket from each another */
2046
 
 
2047
 
    dev->bs = NULL;
2048
 
    bs->dev = NULL;
2049
 
 
2050
 
    /* Discard the entry */
2051
 
 
2052
 
    if (bs->clientname)
2053
 
        free(bs->clientname);
2054
 
    bs->clientname = NULL;
2055
 
 
2056
 
    if (bs->clientip)
2057
 
        free(bs->clientip);
2058
 
    bs->clientip = NULL;
2059
 
 
2060
 
    free (bs->spec);
2061
 
    free (bs);
2062
 
 
2063
 
    return 1;   /* (success) */
2064
 
}
2065
 
 
2066
 
/*-------------------------------------------------------------------*/
2067
 
/* unix_socket   create and bind a Unix domain socket                */
2068
 
/*-------------------------------------------------------------------*/
2069
 
 
2070
 
#include <sys/un.h>     /* (need "sockaddr_un") */
2071
 
 
2072
 
int unix_socket (char* path)
2073
 
{
2074
 
    struct sockaddr_un addr;
2075
 
    int sd;
2076
 
 
2077
 
    logdebug ("unix_socket(%s)\n", path);
2078
 
 
2079
 
    if (strlen (path) > sizeof(addr.sun_path) - 1)
2080
 
    {
2081
 
        logmsg (_("HHCSD008E Socket pathname \"%s\" exceeds limit of %d\n"),
2082
 
            path, (int) sizeof(addr.sun_path) - 1);
2083
 
        return -1;
2084
 
    }
2085
 
 
2086
 
    addr.sun_family = AF_UNIX;
2087
 
    strcpy (addr.sun_path, path); /* guaranteed room by above check */
2088
 
    sd = socket (PF_UNIX, SOCK_STREAM, 0);
2089
 
 
2090
 
    if (sd == -1)
2091
 
    {
2092
 
        logmsg (_("HHCSD009E Error creating socket for %s: %s\n"),
2093
 
            path, strerror(errno));
2094
 
        return -1;
2095
 
    }
2096
 
 
2097
 
    unlink (path);
2098
 
    fchmod (sd, 0700);
2099
 
 
2100
 
    if (0
2101
 
        || bind (sd, (struct sockaddr*) &addr, sizeof(addr)) == -1
2102
 
        || listen (sd, 5) == -1
2103
 
        )
2104
 
    {
2105
 
        logmsg (_("HHCSD010E Failed to bind or listen on socket %s: %s\n"),
2106
 
            path, strerror(errno));
2107
 
        return -1;
2108
 
    }
2109
 
 
2110
 
    return sd;
2111
 
}
2112
 
 
2113
 
/*-------------------------------------------------------------------*/
2114
 
/* inet_socket   create and bind a regular TCP/IP socket             */
2115
 
/*-------------------------------------------------------------------*/
2116
 
int inet_socket (char* spec)
2117
 
{
2118
 
    /* We need a copy of the path to overwrite a ':' with '\0' */
2119
 
 
2120
 
    char buf[sizeof(((DEVBLK*)0)->filename)];
2121
 
    char* colon;
2122
 
    char* node;
2123
 
    char* service;
2124
 
    int sd;
2125
 
    int one = 1;
2126
 
    struct sockaddr_in sin;
2127
 
 
2128
 
    logdebug("inet_socket(%s)\n", spec);
2129
 
 
2130
 
    memset(&sin, 0, sizeof(sin));
2131
 
    sin.sin_family = AF_INET;
2132
 
    strcpy(buf, spec);
2133
 
    colon = strchr(buf, ':');
2134
 
 
2135
 
    if (colon)
2136
 
    {
2137
 
        *colon = '\0';
2138
 
        node = buf;
2139
 
        service = colon + 1;
2140
 
    }
2141
 
    else
2142
 
    {
2143
 
        node = NULL;
2144
 
        service = buf;
2145
 
    }
2146
 
 
2147
 
    if (!node)
2148
 
        sin.sin_addr.s_addr = INADDR_ANY;
2149
 
    else
2150
 
    {
2151
 
        struct hostent* he = gethostbyname(node);
2152
 
 
2153
 
        if (!he)
2154
 
        {
2155
 
            logmsg (_("HHCSD011E Failed to determine IP address from %s\n"),
2156
 
                node);
2157
 
            return -1;
2158
 
        }
2159
 
 
2160
 
        memcpy(&sin.sin_addr, he->h_addr_list[0], sizeof(sin.sin_addr));
2161
 
    }
2162
 
 
2163
 
    if (isdigit(service[0]))
2164
 
    {
2165
 
        sin.sin_port = htons(atoi(service));
2166
 
    }
2167
 
    else
2168
 
    {
2169
 
        struct servent* se = getservbyname(service, "tcp");
2170
 
 
2171
 
        if (!se)
2172
 
        {
2173
 
            logmsg (_("HHCSD012E Failed to determine port number from %s\n"),
2174
 
                service);
2175
 
            return -1;
2176
 
        }
2177
 
 
2178
 
        sin.sin_port = se->s_port;
2179
 
    }
2180
 
 
2181
 
    sd = socket (PF_INET, SOCK_STREAM, 0);
2182
 
 
2183
 
    if (sd == -1)
2184
 
    {
2185
 
        logmsg (_("HHCSD013E Error creating socket for %s: %s\n"),
2186
 
            spec, strerror(errno));
2187
 
        return -1;
2188
 
    }
2189
 
 
2190
 
    setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
2191
 
 
2192
 
    if (0
2193
 
        || bind (sd, (struct sockaddr*) &sin, sizeof(sin)) == -1
2194
 
        || listen (sd, 5) == -1
2195
 
        )
2196
 
    {
2197
 
        logmsg (_("HHCSD014E Failed to bind or listen on socket %s: %s\n"),
2198
 
            spec, strerror(errno));
2199
 
        return -1;
2200
 
    }
2201
 
 
2202
 
    return sd;
2203
 
}
2204
 
 
2205
 
/*-------------------------------------------------------------------*/
2206
 
/* add_socket_devices_to_fd_set   add all bound socket devices'      */
2207
 
/*                                listening sockets to the FD_SET    */
2208
 
/*-------------------------------------------------------------------*/
2209
 
int add_socket_devices_to_fd_set (fd_set* readset, int maxfd)
2210
 
{
2211
 
    DEVBLK* dev;
2212
 
    bind_struct* bs;
2213
 
    LIST_ENTRY*  pListEntry;
2214
 
 
2215
 
    obtain_lock(&bind_lock);
2216
 
 
2217
 
    pListEntry = bind_head.Flink;
2218
 
 
2219
 
    while (pListEntry != &bind_head)
2220
 
    {
2221
 
        bs = CONTAINING_RECORD(pListEntry,bind_struct,bind_link);
2222
 
 
2223
 
        if (bs->sd != -1)           /* if listening for connections, */
2224
 
        {
2225
 
            dev = bs->dev;
2226
 
 
2227
 
            if (dev->fd == -1)      /* and not already connected, */
2228
 
            {
2229
 
                FD_SET(bs->sd, readset);    /* then add file to set */
2230
 
 
2231
 
                if (bs->sd > maxfd)
2232
 
                    maxfd = bs->sd;
2233
 
            }
2234
 
        }
2235
 
 
2236
 
        pListEntry = pListEntry->Flink;
2237
 
    }
2238
 
 
2239
 
    release_lock(&bind_lock);
2240
 
 
2241
 
    return maxfd;
2242
 
}
2243
 
 
2244
 
/*-------------------------------------------------------------------*/
2245
 
/* check_socket_devices_for_connections                              */
2246
 
/*-------------------------------------------------------------------*/
2247
 
void check_socket_devices_for_connections (fd_set* readset)
2248
 
{
2249
 
    bind_struct* bs;
2250
 
    LIST_ENTRY*  pListEntry;
2251
 
 
2252
 
    obtain_lock(&bind_lock);
2253
 
 
2254
 
    pListEntry = bind_head.Flink;
2255
 
 
2256
 
    while (pListEntry != &bind_head)
2257
 
    {
2258
 
        bs = CONTAINING_RECORD(pListEntry,bind_struct,bind_link);
2259
 
 
2260
 
        if (bs->sd != -1 && FD_ISSET(bs->sd, readset))
2261
 
        {
2262
 
            /* Note: there may be other connection requests
2263
 
             * waiting to be serviced, but we'll catch them
2264
 
             * the next time the panel thread calls us. */
2265
 
 
2266
 
            release_lock(&bind_lock);
2267
 
            socket_device_connection_handler(bs);
2268
 
            return;
2269
 
        }
2270
 
 
2271
 
        pListEntry = pListEntry->Flink;
2272
 
    }
2273
 
 
2274
 
    release_lock(&bind_lock);
2275
 
}
2276
 
 
2277
 
/*-------------------------------------------------------------------*/
2278
 
/* socket_device_connection_handler                                  */
2279
 
/*-------------------------------------------------------------------*/
2280
 
void socket_device_connection_handler (bind_struct* bs)
2281
 
{
2282
 
    struct sockaddr_in  client;         /* Client address structure  */
2283
 
    struct hostent*     pHE;            /* Addr of hostent structure */
2284
 
    socklen_t           namelen;        /* Length of client structure*/
2285
 
    char*               clientip;       /* Addr of client ip address */
2286
 
    char*               clientname;     /* Addr of client hostname   */
2287
 
    DEVBLK*             dev;            /* Device Block pointer      */
2288
 
    int                 csock;          /* Client socket             */
2289
 
 
2290
 
    dev = bs->dev;
2291
 
 
2292
 
    logdebug("socket_device_connection_handler(dev=%4.4X)\n",
2293
 
        dev->devnum);
2294
 
 
2295
 
    /* Obtain the device lock */
2296
 
 
2297
 
    obtain_lock (&dev->lock);
2298
 
 
2299
 
    /* Reject if device is busy or interrupt pending */
2300
 
 
2301
 
    if (dev->busy || dev->pending || (dev->scsw.flag3 & SCSW3_SC_PEND))
2302
 
    {
2303
 
        release_lock (&dev->lock);
2304
 
        logmsg (_("HHCSD015E Connect to device %4.4X (%s) rejected; "
2305
 
            "device busy or interrupt pending\n"),
2306
 
            dev->devnum, bs->spec);
2307
 
        return;
2308
 
    }
2309
 
 
2310
 
    /* Reject if previous connection not closed (should not occur) */
2311
 
 
2312
 
    if (dev->fd != -1)
2313
 
    {
2314
 
        release_lock (&dev->lock);
2315
 
        logmsg (_("HHCSD016E Connect to device %4.4X (%s) rejected; "
2316
 
            "client %s (%s) still connected\n"),
2317
 
            dev->devnum, bs->spec, bs->clientip, bs->clientname);
2318
 
        return;
2319
 
    }
2320
 
 
2321
 
    /* Accept the connection... */
2322
 
 
2323
 
    csock = accept(bs->sd, 0, 0);
2324
 
 
2325
 
    if (csock == -1)
2326
 
    {
2327
 
        release_lock (&dev->lock);
2328
 
        logmsg (_("HHCSD017E Connect to device %4.4X (%s) failed: %s\n"),
2329
 
            dev->devnum, bs->spec, strerror(errno));
2330
 
        return;
2331
 
    }
2332
 
 
2333
 
    /* Determine the connected client's IP address and hostname */
2334
 
 
2335
 
    namelen = sizeof(client);
2336
 
    clientip = NULL;
2337
 
    clientname = "host name unknown";
2338
 
 
2339
 
    if (1
2340
 
        && getpeername(csock, (struct sockaddr*) &client, &namelen) == 0
2341
 
        && (clientip = inet_ntoa(client.sin_addr)) != NULL
2342
 
        && (pHE = gethostbyaddr((unsigned char*)(&client.sin_addr),
2343
 
            sizeof(client.sin_addr), AF_INET)) != NULL
2344
 
        && pHE->h_name && *pHE->h_name
2345
 
        )
2346
 
    {
2347
 
        clientname = (char*) pHE->h_name;
2348
 
    }
2349
 
 
2350
 
    /* Log the connection */
2351
 
 
2352
 
    if (clientip)
2353
 
    {
2354
 
        logmsg (_("HHCSD018I %s (%s) connected to device %4.4X (%s)\n"),
2355
 
            clientip, clientname, dev->devnum, bs->spec);
2356
 
    }
2357
 
    else
2358
 
    {
2359
 
        logmsg (_("HHCSD019I <unknown> connected to device %4.4X (%s)\n"),
2360
 
            dev->devnum, bs->spec);
2361
 
    }
2362
 
 
2363
 
    /* Save the connected client information in the bind_struct */
2364
 
 
2365
 
    if (bs->clientip)   free(bs->clientip);
2366
 
    if (bs->clientname) free(bs->clientname);
2367
 
 
2368
 
    bs->clientip   = safe_strdup(clientip);
2369
 
    bs->clientname = safe_strdup(clientname);
2370
 
 
2371
 
    /* Indicate that a client is now connected to device (prevents
2372
 
     * listening for new connections until THIS client disconnects).
2373
 
     */
2374
 
 
2375
 
    dev->fd = csock;        /* (indicate client connected to device) */
2376
 
 
2377
 
    /* Release the device lock */
2378
 
 
2379
 
    release_lock (&dev->lock);
2380
 
 
2381
 
    /* Raise unsolicited device end interrupt for the device */
2382
 
 
2383
 
    device_attention (dev, CSW_DE);
2384
 
}
2385
 
 
2386
 
/*-------------------------------------------------------------------*/
2387
 
/* safe_strdup   make copy of string and return a pointer to it      */
2388
 
/*-------------------------------------------------------------------*/
2389
 
char* safe_strdup (char* str)
2390
 
{
2391
 
    char* newstr;
2392
 
    if (!str) return NULL;
2393
 
    newstr = malloc (strlen (str) + 1);
2394
 
    if (!newstr) return NULL;
2395
 
    strcpy (newstr, str);   /* (guaranteed room) */
2396
 
    return newstr;
2397
 
}