1 | #ifndef _POSIX_SOURCE |
---|
2 | #define _POSIX_SOURCE |
---|
3 | #endif |
---|
4 | |
---|
5 | /* Support routines for terminal I/O. This module defines the following |
---|
6 | Fortran-callable routines: GROTER, GRCTER, GRWTER, GRPTER. */ |
---|
7 | |
---|
8 | #include <stdio.h> |
---|
9 | #include <termios.h> |
---|
10 | #include <string.h> |
---|
11 | #include <fcntl.h> |
---|
12 | #include <unistd.h> |
---|
13 | |
---|
14 | #ifdef PG_PPU |
---|
15 | #define GROTER groter_ |
---|
16 | #define GRWTER grwter_ |
---|
17 | #define GRCTER grcter_ |
---|
18 | #define GRPTER grpter_ |
---|
19 | #else |
---|
20 | #define GROTER groter |
---|
21 | #define GRWTER grwter |
---|
22 | #define GRCTER grcter |
---|
23 | #define GRPTER grpter |
---|
24 | #endif |
---|
25 | |
---|
26 | /* Open a channel to the device specified by 'cdev'. |
---|
27 | * |
---|
28 | * cdev I The name of the device to be opened |
---|
29 | * ldev I Number of valid characters in cdev |
---|
30 | * groter O The open channel number (-1 indicates an error) |
---|
31 | */ |
---|
32 | int GROTER(cdev, ldev, cdev_len) |
---|
33 | char *cdev; int *ldev; |
---|
34 | int cdev_len; |
---|
35 | { |
---|
36 | int fd; /* The returned file descriptor */ |
---|
37 | char name[64]; /* A copy of the given terminal device name */ |
---|
38 | /* |
---|
39 | * Make a copy of the given file if there is sufficient room in name[]. |
---|
40 | */ |
---|
41 | if(*ldev <= sizeof(name)-1) { |
---|
42 | strncpy(name, cdev, *ldev); |
---|
43 | name[*ldev] = '\0'; |
---|
44 | } else { |
---|
45 | fprintf(stderr, "groter: Terminal file name too long.\n"); |
---|
46 | return -1; |
---|
47 | }; |
---|
48 | /* |
---|
49 | * Open the terminal. |
---|
50 | */ |
---|
51 | if((fd = open(name, 2)) == -1) { |
---|
52 | perror(name); |
---|
53 | return -1; |
---|
54 | }; |
---|
55 | return fd; |
---|
56 | } |
---|
57 | |
---|
58 | |
---|
59 | /* Close a previously opened channel. |
---|
60 | * |
---|
61 | * fd I The channel number to be closed |
---|
62 | */ |
---|
63 | void GRCTER(fd) |
---|
64 | int *fd; |
---|
65 | { |
---|
66 | close(*fd); |
---|
67 | return; |
---|
68 | } |
---|
69 | |
---|
70 | /* Write lbuf bytes from cbuf to the channel fd. Data is written without |
---|
71 | * any formating. |
---|
72 | * |
---|
73 | * fd I The channel number |
---|
74 | * cbuf I Character array of data to be written |
---|
75 | * lbuf I/O The number of bytes to write, set to zero on return |
---|
76 | */ |
---|
77 | void GRWTER(fd, cbuf, lbuf, cbuf_len) |
---|
78 | int *fd; char *cbuf; int *lbuf; int cbuf_len; |
---|
79 | { |
---|
80 | int nwritten = write (*fd, cbuf, *lbuf); |
---|
81 | if (nwritten != *lbuf) |
---|
82 | perror("Error writing to graphics device"); |
---|
83 | *lbuf = 0; |
---|
84 | return; |
---|
85 | } |
---|
86 | |
---|
87 | /* Write prompt string on terminal and then read response. This version |
---|
88 | * will try to read lbuf characters. |
---|
89 | * |
---|
90 | * fd I The channel number |
---|
91 | * cprom I An optional prompt string |
---|
92 | * lprom I Number of valid characters in cprom |
---|
93 | * cbuf O Character array of data read |
---|
94 | * lbuf I/O The number of bytes to read, on return number read |
---|
95 | */ |
---|
96 | void GRPTER(fd, cprom, lprom, cbuf, lbuf, cprom_len, cbuf_len) |
---|
97 | int *fd; char *cprom; int *lprom; char *cbuf; int *lbuf; |
---|
98 | int cprom_len; int cbuf_len; |
---|
99 | { |
---|
100 | char *buff = cbuf; /* C pointer to FORTRAN string */ |
---|
101 | int ndone=0; /* The number of characters read */ |
---|
102 | struct termios term; /* Terminal mode flags */ |
---|
103 | /* |
---|
104 | * Get the current set of terminal mode flags. |
---|
105 | */ |
---|
106 | if(tcgetattr(*fd, &term)==0) { |
---|
107 | struct termios saveterm; /* Saved terminal attributes */ |
---|
108 | int ntry; /* The number of characters still to be read */ |
---|
109 | int nread; /* The number of characters read in one iteration */ |
---|
110 | /* |
---|
111 | * Save the existing terminal mode flags to be restored later. |
---|
112 | */ |
---|
113 | saveterm = term; |
---|
114 | /* |
---|
115 | * Enable raw single character input. |
---|
116 | */ |
---|
117 | term.c_lflag &= ~ICANON; |
---|
118 | term.c_cc[VMIN] = 1; |
---|
119 | /* |
---|
120 | * Install the new terminal flags after first waiting for all pending |
---|
121 | * output to be delivered to the terminal and after discarding any |
---|
122 | * lingering input. |
---|
123 | */ |
---|
124 | tcsetattr(*fd, TCSAFLUSH, &term); |
---|
125 | /* |
---|
126 | * Prompt for input. |
---|
127 | */ |
---|
128 | if(*lprom>0) write(*fd, cprom, *lprom); |
---|
129 | /* |
---|
130 | * Read up to 'ntry' characters from the terminal. |
---|
131 | */ |
---|
132 | ndone = 0; |
---|
133 | ntry = *lbuf; |
---|
134 | do { |
---|
135 | nread = read(*fd, &buff[ndone], ntry); |
---|
136 | ndone += nread; |
---|
137 | ntry -= nread; |
---|
138 | } while(nread>0 && ntry>0); |
---|
139 | /* |
---|
140 | * Restore the previous terminal mode flags. |
---|
141 | */ |
---|
142 | tcsetattr(*fd, TCSAFLUSH, &saveterm); |
---|
143 | }; |
---|
144 | *lbuf=ndone; |
---|
145 | return; |
---|
146 | } |
---|