|
|
1.1 root 1: /*
2: * shell buffered IO and formatted output
3: */
4:
5: static char *RCSid = "$Header: io.c,v 3.1 88/11/03 09:16:11 egisin Exp $";
6:
7: #include <stddef.h>
8: #include <stdlib.h>
9: #include <stdio.h>
10: #include <errno.h>
11: #include <unistd.h>
12: #include <fcntl.h>
13: #include <signal.h>
14: #include <setjmp.h>
15: #if __STDC__
16: #include <stdarg.h>
17: #else
18: #include <varargs.h>
19: #endif
20: #include "sh.h"
21:
22: #if 0
23: /* fputc with ^ escaping */
24: static void
25: fzotc(c, f)
26: register int c;
27: register FILE *f;
28: {
29: if ((c&0x60) == 0) { /* C0|C1 */
30: putc((c&0x80) ? '$' : '^', f);
31: putc((c&0x7F|0x40), f);
32: } else if ((c&0x7F) == 0x7F) { /* DEL */
33: putc((c&0x80) ? '$' : '^', f);
34: putc('?', f);
35: } else
36: putc(c, f);
37: }
38: #endif
39:
40: /*
41: * formatted output functions
42: */
43:
44: /* shellf(...); error() */
45: int
46: #if COHERENT
47: errorf(fmt)
48: char *fmt;
49: {
50: fprintf(shlout, "%r", &fmt);
51: #else
52: #if __STDC__
53: errorf(Const char *fmt, ...) {
54: #else
55: errorf(va_alist) va_dcl
56: {
57: char *fmt;
58: #endif
59: va_list va;
60:
61: #if __STDC__
62: va_start(va, fmt);
63: #else
64: va_start(va);
65: fmt = va_arg(va, char *);
66: #endif
67: vfprintf(shlout, fmt, va);
68: va_end(va);
69: /*fflush(shlout);*/
70: #endif
71: error();
72: }
73:
74: /* printf to shlout (stderr) */
75: int
76: #if COHERENT
77: shellf(fmt)
78: char *fmt;
79: {
80: fprintf(shlout, "%r", &fmt);
81: #else
82: #if __STDC__
83: shellf(Const char *fmt, ...) {
84: #else
85: shellf(va_alist) va_dcl
86: {
87: char *fmt;
88: #endif
89: va_list va;
90:
91: #if __STDC__
92: va_start(va, fmt);
93: #else
94: va_start(va);
95: fmt = va_arg(va, char *);
96: #endif
97: vfprintf(shlout, fmt, va);
98: va_end(va);
99: #endif
100: return 0;
101: }
102:
103: /*
104: * We have a stdio stream for any open shell file descriptors (0-9)
105: */
106: FILE * shf [NUFILE]; /* map shell fd to FILE * */
107:
108: /* open stream for shell fd */
109: void
110: fopenshf(fd)
111: int fd;
112: {
113: if (shf[fd] != NULL)
114: return;
115: #if !COHERENT
116: if (fd <= 2)
117: _iob[fd]._flag = 0; /* re-use stdin, stdout, stderr */
118: #endif
119: shf[fd] = fdopen(fd, "r+w");
120: if (shf[fd] == NULL)
121: return;
122: setvbuf(shf[fd], (char*)NULL, _IOFBF, (size_t)BUFSIZ);
123: }
124:
125: /* flush stream assoc with fd */
126: /* todo: either fseek (K&R) or fflush (ANSI) will "flush" IO streams */
127: void
128: flushshf(fd)
129: int fd;
130: {
131: if (shf[fd] != NULL)
132: fseek(shf[fd], 0L, 1); /* questionable */
133: }
134:
135: /*
136: * move fd from user space (0<=fd<10) to shell space (fd>=10)
137: */
138: int
139: savefd(fd)
140: int fd;
141: {
142: int nfd;
143:
144: if (fd < FDBASE) {
145: flushshf(fd);
146: nfd = fcntl(fd, F_DUPFD, FDBASE);
147: if (nfd < 0)
148: if (errno == EBADF)
149: return -1;
150: else
151: errorf("too many files open in shell\n");
152: #if !COHERENT
153: (void) fcntl(nfd, F_SETFD, FD_CLEXEC);
154: #endif
155: close(fd);
156: } else
157: nfd = fd;
158: return nfd;
159: }
160:
161: void
162: restfd(fd, ofd)
163: int fd, ofd;
164: {
165: if (ofd == 0) /* not saved (e.savefd) */
166: return;
167: flushshf(fd);
168: close(fd);
169: if (ofd < 0) /* original fd closed */
170: return;
171: (void) fcntl(ofd, F_DUPFD, fd);
172: close(ofd);
173: }
174:
175: void
176: openpipe(pv)
177: register int *pv;
178: {
179: if (pipe(pv) < 0)
180: errorf("can't create pipe - try again\n");
181: pv[0] = savefd(pv[0]);
182: pv[1] = savefd(pv[1]);
183: }
184:
185: void
186: closepipe(pv)
187: register int *pv;
188: {
189: close(pv[0]);
190: close(pv[1]);
191: }
192:
193: /*
194: * temporary files
195: */
196:
197: struct temp *
198: maketemp(ap)
199: Area *ap;
200: {
201: register struct temp *tp;
202: static unsigned int inc = 0;
203: char path [PATH];
204:
205: sprintf(path, "/tmp/sh%05u%02u", (unsigned)getpid(), inc++);
206: /* we could create the thing now with 600 mode */
207: tp = (struct temp *) alloc(sizeof(struct temp), ap);
208: tp->next = NULL;
209: tp->name = strsave(path, ap);
210: return tp;
211: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.