1 #line 982 "../../src/builtin/snarf.m4"
2 /* -*- buffer-read-only: t -*- vi: set ro:
3 THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT.
4 */
5 #line 982
6 #ifdef HAVE_CONFIG_H
7 #line 982
8 # include <config.h>
9 #line 982
10 #endif
11 #line 982
12 #include <sys/types.h>
13 #line 982
14
15 #line 982
16 #include "mailfromd.h"
17 #line 982
18 #include "prog.h"
19 #line 982
20 #include "builtin.h"
21 #line 982
22
23 #line 180 "io.bi"
24 static mu_debug_handle_t debug_handle;
25 #line 982 "../../src/builtin/snarf.m4"
26
27 #line 1022 "../../src/builtin/snarf.m4"
28
29 /* End of snarf.m4 */
30 #line 1 "io.bi"
31 /* This file is part of Mailfromd. -*- c -*-
32 Copyright (C) 2006-2021 Sergey Poznyakoff
33
34 This program is free software; you can redistribute it and/or modify
35 it under the terms of the GNU General Public License as published by
36 the Free Software Foundation; either version 3, or (at your option)
37 any later version.
38
39 This program is distributed in the hope that it will be useful,
40 but WITHOUT ANY WARRANTY; without even the implied warranty of
41 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42 GNU General Public License for more details.
43
44 You should have received a copy of the GNU General Public License
45 along with this program. If not, see <http://www.gnu.org/licenses/>. */
46
47
48
49 #include <mflib/status.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <sys/wait.h>
53 #include "global.h"
54 #include "msg.h"
55
56 static size_t nstreams = MAX_IOSTREAMS;
57
58 static struct mu_cfg_param io_cfg_param[] = {
59 { "max-streams", mu_c_size, &nstreams, 0, NULL,
60 N_("Maximum number of stream descriptors.") },
61 { NULL }
62 };
63
64 struct io_stream {
65 char *name;
66 mu_locker_t lock;
67 int fd[2];
68 pid_t pid;
69 char *buf;
70 size_t bufsize;
71 int (*shutdown)(struct io_stream *, int what);
72 void (*cleanup)(void*);
73 void *cleanup_data;
74 char *delim;
75 };
76
77 #define IFD(s) ((s).fd[0])
78 #define OFD(s) ((s).fd[1] == -1 ? (s).fd[0] : (s).fd[1])
79
80 static void
flush_stream(struct io_stream * str)81 flush_stream(struct io_stream *str)
82 {
83 /*FIXME*/
84 }
85
86 static void
close_stream(struct io_stream * str)87 close_stream(struct io_stream *str)
88 {
89 if (OFD(*str) == -1)
90 return;
91 flush_stream(str);
92 close(OFD(*str));
93 if (IFD(*str) != -1)
94 close(IFD(*str));
95 if (str->pid) {
96 int status;
97 waitpid(str->pid, &status, 0);
98 }
99 str->fd[0] = -1;
100 str->fd[1] = -1;
101 str->pid = 0;
102 if (str->cleanup)
103 str->cleanup(str->cleanup_data);
104 str->cleanup = NULL;
105 str->cleanup_data = NULL;
106 if (str->name) {
107 free(str->name);
108 str->name = NULL;
109 }
110 if (str->delim) {
111 free(str->delim);
112 str->delim = NULL;
113 }
114 }
115
116 /* Read bytes from the stream STR into its buffer, until
117 DELIM is encountered. Return number of bytes read. */
118 static int
read_stream_delim(struct io_stream * str,char * delim)119 read_stream_delim(struct io_stream *str, char *delim)
120 {
121 int fd = IFD(*str);
122 size_t i = 0;
123 int rc;
124 size_t delim_len = strlen(delim);
125
126 for (;;) {
127 if (str->bufsize == i) {
128 if (str->bufsize == 0)
129 str->bufsize = 16;
130 str->buf = mu_2nrealloc(str->buf, &str->bufsize,
131 sizeof str->buf[1]);
132 }
133 rc = read(fd, str->buf + i, 1);
134 if (rc == -1)
135 return -1;
136 else if (rc == 0)
137 return 0;
138 i++;
139 if (i >= delim_len &&
140 memcmp(str->buf + i - delim_len, delim, delim_len) == 0) {
141 str->buf[i - delim_len] = 0;
142 break;
143 }
144 }
145 return i;
146 }
147
148 #define REDIRECT_STDIN_P(f) ((f) & (O_WRONLY|O_RDWR))
149 #define REDIRECT_STDOUT_P(f) (!((f) & O_WRONLY))
150
151 #define STDERR_SHUT 0
152 #define STDERR_NULL 1
153 #define STDERR_LOG 2
154 #define STDERR_FILE 3
155 #define STDERR_FILE_APPEND 4
156
157 #define LOG_TAG_PFX "mailfromd:"
158 #define LOG_TAG_PFX_LEN (sizeof(LOG_TAG_PFX)-1)
159
160 static void
stderr_to_log(char * arg,const char * cmd)161 stderr_to_log(char *arg, const char *cmd)
162 {
163 int p[2];
164 pid_t pid;
165
166 if (pipe(p)) {
167 mu_error(_("pipe failed: %s"), mu_strerror(errno));
168 close(2);
169 return;
170 }
171
172 pid = fork();
173
174 if (pid == (pid_t) -1) {
175 mu_error(_("fork failed: %s"), mu_strerror(errno));
176 close(p[0]);
177 close(p[1]);
178 close(2);
179 return;
180 }
181
182 /* Child */
183 if (pid == 0) {
184 FILE *fp;
185 fd_set fdset;
186 size_t len;
187 char buf[1024];
188 char *tag;
189 int fac = mu_log_facility, pri = LOG_ERR;
190
191 if (arg) {
192 char *p = strchr(arg, '.');
193
194 if (p)
195 *p++ = 0;
196 if (mu_string_to_syslog_facility(arg, &fac)) {
197 mu_error(_("unknown syslog facility (%s), "
198 "redirecting stderr to %s"),
199 arg,
200 mu_syslog_facility_to_string(fac));
201 }
202
203 if (p && mu_string_to_syslog_priority(p, &pri)) {
204 mu_error(_("unknown syslog priority (%s), "
205 "redirecting stderr to %s"),
206 arg,
207 mu_syslog_priority_to_string(pri));
208 }
209 }
210
211 #line 180 "io.bi"
212
213 #line 180
214 mu_debug(debug_handle, MU_DEBUG_TRACE2,("redirecting stderr to syslog %s.%s",
215 mu_syslog_facility_to_string(fac),
216 mu_syslog_priority_to_string(pri)));
217 #line 184
218
219 len = strcspn(cmd, " \t");
220 tag = malloc(LOG_TAG_PFX_LEN + len + 1);
221 if (!tag)
222 tag = (char*) cmd;
223 else {
224 strcpy(tag, LOG_TAG_PFX);
225 memcpy(tag + LOG_TAG_PFX_LEN, cmd, len);
226 tag[LOG_TAG_PFX_LEN + len] = 0;
227 }
228 mf_proctitle_format("%s redirector", cmd);
229
230 FD_ZERO(&fdset);
231 FD_SET(p[0], &fdset);
232 logger_fdset(&fdset);
233 close_fds_except(&fdset);
234
235 fp = fdopen(p[0], "r");
236 logger_open();
237 while (fgets(buf, sizeof(buf), fp))
238 syslog(pri, "%s", buf);
239 exit(0);
240 }
241
242 /* Parent */
243 close(p[0]);
244 dup2(p[1], 2);
245 close(p[1]);
246 }
247
248 static void
stderr_handler(int mode,char * arg,const char * cmd)249 stderr_handler(int mode, char *arg, const char *cmd)
250 {
251 int fd;
252 int append = O_TRUNC;
253
254 switch (mode) {
255 case STDERR_SHUT:
256 close(2);
257 break;
258
259 case STDERR_NULL:
260 arg = "/dev/null";
261 case STDERR_FILE_APPEND:
262 append = O_APPEND;
263 case STDERR_FILE:
264 if (!arg || !*arg) {
265 close(2);
266 break;
267 }
268
269 #line 234
270
271 #line 234
272 mu_debug(debug_handle, MU_DEBUG_TRACE2,("redirecting stderr to %s", arg));
273 fd = open(arg, O_CREAT|O_WRONLY|append, 0644);
274 if (fd < 0) {
275 mu_error(_("cannot open file %s for appending: %s"),
276 arg, mu_strerror(errno));
277 close(2);
278 return;
279 }
280 if (fd != 2) {
281 dup2(fd, 2);
282 close(fd);
283 }
284 break;
285
286 case STDERR_LOG:
287 stderr_to_log(arg, cmd);
288 }
289 }
290
291 static void
parse_stderr_redirect(const char ** pcmd,int * perr,char ** parg)292 parse_stderr_redirect(const char **pcmd, int *perr, char **parg)
293 {
294 int err;
295 size_t len;
296 char *arg;
297 const char *cmdline = *pcmd;
298
299 while (*cmdline && mu_isspace(*cmdline))
300 cmdline++;
301 if (strncmp(cmdline, "2>file:", 7) == 0) {
302 cmdline += 7;
303 err = STDERR_FILE;
304 } else if (strncmp(cmdline, "2>>file:", 8) == 0) {
305 cmdline += 8;
306 err = STDERR_FILE_APPEND;
307 } else if (strncmp(cmdline, "2>null:", 7) == 0) {
308 cmdline += 7;
309 err = STDERR_NULL;
310 } else if (strncmp(cmdline, "2>syslog:", 9) == 0) {
311 cmdline += 9;
312 err = STDERR_LOG;
313 } else
314 return;
315
316 len = strcspn(cmdline, " \t");
317 if (len > 0 && cmdline[len-1] == 0)
318 return;
319 if (len == 0)
320 arg = NULL;
321 else {
322 arg = malloc(len + 1);
323 if (!arg)
324 return;
325 memcpy(arg, cmdline, len);
326 arg[len] = 0;
327 }
328
329 *pcmd = cmdline + len;
330 *perr = err;
331 *parg = arg;
332 }
333
334
335 static int
open_program_stream_ioe(eval_environ_t env,struct io_stream * str,const char * cmdline,int flags,int ioe[2])336 open_program_stream_ioe(eval_environ_t env,
337 struct io_stream *str, const char *cmdline,
338 int flags,
339 int ioe[2])
340 {
341 int rightp[2], leftp[2];
342 int rc = 0;
343 pid_t pid;
344 int err = STDERR_SHUT;
345 char *arg = NULL;
346 struct mu_wordsplit ws;
347
348 parse_stderr_redirect(&cmdline, &err, &arg);
349 while (*cmdline && (*cmdline == ' ' || *cmdline == '\t'))
350 cmdline++;
351
352 if (REDIRECT_STDIN_P(flags)) {
353 if (pipe(leftp)) {
354 mu_diag_funcall(MU_DIAG_ERROR, "pipe", "leftp",
355 errno);
356 free(arg);
357 (
358 #line 319
359 env_throw_bi(env, mfe_failure, NULL, "pipe failed")
360 #line 319
361 );
362 }
363 }
364
365 if (REDIRECT_STDOUT_P(flags)) {
366 if (pipe(rightp)) {
367 mu_diag_funcall(MU_DIAG_ERROR, "pipe", "rightp",
368 errno);
369 free(arg);
370 if (REDIRECT_STDIN_P(flags)) {
371 close(leftp[0]);
372 close(leftp[1]);
373 }
374 }
375 }
376
377 switch (pid = fork()) {
378 /* The child branch. */
379 case 0:
380 /* attach the pipes */
381
382 /* Right-end */
383 if (REDIRECT_STDOUT_P(flags)) {
384 if (rightp[1] != 1)
385 dup2(rightp[1], 1);
386 } else if (ioe && ioe[1] != -1 && ioe[1] != 1) {
387 dup2(ioe[1], 1);
388 }
389
390 /* Left-end */
391 if (REDIRECT_STDIN_P(flags)) {
392 if (leftp[0] != 0)
393 dup2(leftp[0], 0);
394 } else if (ioe && ioe[0] != -1 && ioe[0] != 0) {
395 dup2(ioe[0], 0);
396 }
397
398 if (ioe && ioe[2] != -1 && ioe[2] != 2)
399 dup2(ioe[2], 2);
400 else
401 stderr_handler(err, arg, cmdline);
402
403 /* Close unneeded descriptors */
404 close_fds_above(2);
405
406
407 #line 364
408
409 #line 364
410 mu_debug(debug_handle, MU_DEBUG_TRACE3,("running %s", cmdline));
411 if (mu_wordsplit(cmdline, &ws,
412 MU_WRDSF_DEFFLAGS & ~MU_WRDSF_CESCAPES)) {
413 mu_error(_("cannot parse command line %s: %s"),
414 cmdline, mu_wordsplit_strerror(&ws));
415 exit(127);
416 }
417 execvp(ws.ws_wordv[0], ws.ws_wordv);
418 mu_error(_("cannot run %s: %s"),
419 cmdline, mu_strerror(errno));
420 exit(127);
421 /********************/
422
423 /* Parent branches: */
424 case -1:
425 /* Fork has failed */
426 /* Restore things */
427 rc = errno;
428 if (REDIRECT_STDOUT_P(flags)) {
429 close(rightp[0]);
430 close(rightp[1]);
431 }
432 if (REDIRECT_STDIN_P(flags)) {
433 close(leftp[0]);
434 close(leftp[1]);
435 }
436 break;
437
438 default:
439 str->pid = pid;
440 if (REDIRECT_STDOUT_P(flags)) {
441 str->fd[0] = rightp[0];
442 close(rightp[1]);
443 } else
444 str->fd[0] = -1;
445
446 if (REDIRECT_STDIN_P(flags)) {
447 str->fd[1] = leftp[1];
448 close(leftp[0]);
449 } else
450 str->fd[1] = -1;
451 }
452 free(arg);
453 return rc;
454 }
455
456 static int
open_program_stream(eval_environ_t env,struct io_stream * str,const char * cmdline,int flags)457 open_program_stream(eval_environ_t env,
458 struct io_stream *str, const char *cmdline,
459 int flags)
460 {
461 return open_program_stream_ioe(env, str, cmdline, flags, NULL);
462 }
463
464 static int
open_file_stream(eval_environ_t env,struct io_stream * str,const char * file,int flags)465 open_file_stream(eval_environ_t env,
466 struct io_stream *str, const char *file, int flags)
467 {
468 str->fd[0] = open(file, flags, 0644); /* FIXME: mode? */
469 if (str->fd[0] == -1)
470 return errno;
471 return 0;
472 }
473
474
475
476 static int
open_parsed_inet_stream(eval_environ_t env,struct io_stream * str,const char * cstr,char * proto,char * port,char * path,int flags)477 open_parsed_inet_stream(eval_environ_t env,
478 struct io_stream *str,
479 const char *cstr,
480 char *proto, char *port, char *path,
481 int flags)
482 {
483 union {
484 struct sockaddr sa;
485 struct sockaddr_in s_in;
486 struct sockaddr_un s_un;
487 #ifdef GACOPYZ_IPV6
488 struct sockaddr_in6 s_in6;
489 #endif
490 } addr;
491
492 socklen_t socklen;
493 int fd;
494 int rc;
495
496 if (!proto
497 || strcmp(proto, "unix") == 0 || strcmp(proto, "local") == 0) {
498 struct stat st;
499
500 if (!(port == NULL))
501 #line 454
502 (
503 #line 454
504 env_throw_bi(env, mfe_failure, NULL, _("invalid connection type: %s; "
505 "port is meaningless for UNIX sockets"),cstr)
506 #line 454
507 )
508 #line 458
509 ;
510
511 if (!(strlen(path) <= sizeof addr.s_un.sun_path))
512 #line 460
513 (
514 #line 460
515 env_throw_bi(env, mfe_range, NULL, _("%s: UNIX socket name too long"),path)
516 #line 460
517 )
518 #line 463
519 ;
520
521 addr.sa.sa_family = PF_UNIX;
522 socklen = sizeof(addr.s_un);
523 strcpy(addr.s_un.sun_path, path);
524
525 if (stat(path, &st)) {
526 (
527 #line 470
528 env_throw_bi(env, mfe_failure, NULL, _("%s: cannot stat socket: %s"),path,strerror(errno))
529 #line 470
530 );
531 #line 473
532 } else {
533 /* FIXME: Check permissions? */
534 if (!(S_ISSOCK(st.st_mode)))
535 #line 475
536 (
537 #line 475
538 env_throw_bi(env, mfe_failure, NULL, _("%s: not a socket"),path)
539 #line 475
540 )
541 #line 478
542 ;
543 }
544
545 } else if (strcmp(proto, "inet") == 0) {
546 short pnum;
547 long num;
548 char *p;
549
550 addr.sa.sa_family = PF_INET;
551 socklen = sizeof(addr.s_in);
552
553 if (!(port != NULL))
554 #line 489
555 (
556 #line 489
557 env_throw_bi(env, mfe_failure, NULL, _("invalid connection type: %s; "
558 "missing port number"),cstr)
559 #line 489
560 )
561 #line 493
562 ;
563
564 num = pnum = strtol(port, &p, 0);
565 if (*p == 0) {
566 if (!(num == pnum))
567 #line 497
568 (
569 #line 497
570 env_throw_bi(env, mfe_range, NULL, _("invalid connection type: "
571 "%s; bad port number"),cstr)
572 #line 497
573 )
574 #line 501
575 ;
576 pnum = htons(pnum);
577 } else {
578 struct servent *sp = getservbyname(port, "tcp");
579
580 if (!(sp != NULL))
581 #line 506
582 (
583 #line 506
584 env_throw_bi(env, mfe_failure, NULL, _("invalid connection type: "
585 "%s; unknown port name"),cstr)
586 #line 506
587 )
588 #line 510
589 ;
590 pnum = sp->s_port;
591 }
592
593 if (!path)
594 addr.s_in.sin_addr.s_addr = INADDR_ANY;
595 else {
596 struct hostent *hp = gethostbyname(path);
597 if (!(hp != NULL))
598 #line 518
599 (
600 #line 518
601 env_throw_bi(env, mfe_failure, NULL, _("unknown host name %s"),path)
602 #line 518
603 )
604 #line 521
605 ;
606 addr.sa.sa_family = hp->h_addrtype;
607 switch (hp->h_addrtype) {
608 case AF_INET:
609 memmove(&addr.s_in.sin_addr, hp->h_addr, 4);
610 addr.s_in.sin_port = pnum;
611 break;
612
613 default:
614 (
615 #line 530
616 env_throw_bi(env, mfe_range, NULL, _("invalid connection type: "
617 "%s; unsupported address family"),cstr)
618 #line 530
619 );
620 #line 534
621 }
622 }
623 #ifdef GACOPYZ_IPV6
624 } else if (strcmp(proto, "inet6") == 0) {
625 struct addrinfo hints;
626 struct addrinfo *res;
627
628 if (!(port != NULL))
629 #line 541
630 (
631 #line 541
632 env_throw_bi(env, mfe_failure, NULL, _("invalid connection type: %s; "
633 "missing port number"),cstr)
634 #line 541
635 )
636 #line 545
637 ;
638
639 memset(&hints, 0, sizeof(hints));
640 hints.ai_family = AF_INET6;
641 hints.ai_socktype = SOCK_STREAM;
642 if (!path)
643 hints.ai_flags |= AI_PASSIVE;
644
645 rc = getaddrinfo(path, port, &hints, &res);
646
647 switch (rc) {
648 case 0:
649 break;
650
651 case EAI_SYSTEM:
652 (
653 #line 560
654 env_throw_bi(env, mfe_failure, NULL, _("%s:%s: cannot parse address: %s"),path,port,strerror(errno))
655 #line 560
656 );
657 #line 563
658
659 case EAI_BADFLAGS:
660 case EAI_SOCKTYPE:
661 (
662 #line 566
663 env_throw_bi(env, mfe_failure, NULL, _("%s:%d: internal error converting %s:%s"),__FILE__,__LINE__,path,port)
664 #line 566
665 );
666 #line 569
667
668 case EAI_MEMORY:
669 mu_alloc_die();
670
671 default:
672 (
673 #line 574
674 env_throw_bi(env, mfe_failure, NULL, "%s:%s: %s",path,port,gai_strerror(rc))
675 #line 574
676 );
677 #line 577
678 }
679
680 socklen = res->ai_addrlen;
681 if (socklen > sizeof(addr)) {
682 freeaddrinfo(res);
683 (
684 #line 582
685 env_throw_bi(env, mfe_failure, NULL, _("%s:%s: address length too big (%lu)"),path,port,(unsigned long) socklen)
686 #line 582
687 );
688 #line 586
689 }
690 memcpy(&addr, res->ai_addr, res->ai_addrlen);
691 freeaddrinfo(res);
692 #endif
693 } else {
694 (
695 #line 591
696 env_throw_bi(env, mfe_range, NULL, _("unsupported protocol: %s"),proto)
697 #line 591
698 );
699 #line 594
700 }
701
702 fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
703 if (!(fd != -1))
704 #line 597
705 (
706 #line 597
707 env_throw_bi(env, mfe_failure, NULL, _("unable to create new socket: %s"),strerror(errno))
708 #line 597
709 )
710 #line 600
711 ;
712
713 /* FIXME: Bind to the source ? */
714
715 rc = connect(fd, &addr.sa, socklen);
716 if (rc) {
717 close(fd);
718 (
719 #line 607
720 env_throw_bi(env, mfe_failure, NULL, _("cannot connect to %s: %s"),cstr,strerror(errno))
721 #line 607
722 );
723 #line 610
724 }
725
726 str->fd[0] = fd;
727 return 0;
728 }
729
730 static int
shutdown_inet_stream(struct io_stream * str,int how)731 shutdown_inet_stream(struct io_stream *str, int how)
732 {
733 switch (how) {
734 case 0:
735 how = SHUT_RD;
736 break;
737
738 case 1:
739 how = SHUT_WR;
740 break;
741
742 case 2:
743 how = SHUT_RDWR;
744 break;
745
746 default:
747 return EINVAL;
748 }
749 if (shutdown(str->fd[0], how))
750 return errno;
751 return 0;
752 }
753
754 static int
open_inet_stream(eval_environ_t env,struct io_stream * str,const char * addr,int flags)755 open_inet_stream(eval_environ_t env,
756 struct io_stream *str, const char *addr, int flags)
757 {
758 int rc;
759 char *proto, *port, *path;
760
761 if (gacopyz_parse_connection(addr, &proto, &port, &path)
762 != MI_SUCCESS)
763 rc = ENOMEM; /* FIXME: or EINVAL? */
764 else {
765 rc = open_parsed_inet_stream(env,
766 str, addr,
767 proto, port, path, flags);
768 str->shutdown = shutdown_inet_stream;
769 free(proto);
770 free(port);
771 free(path);
772 }
773 return rc;
774 }
775
776
777 static void *
alloc_streams()778 alloc_streams()
779 {
780 struct io_stream *p, *stab = mu_calloc(nstreams, sizeof *stab);
781 for (p = stab; p < stab + nstreams; p++)
782 p->fd[0] = p->fd[1] = -1;
783 return stab;
784 }
785
786 static void
destroy_streams(void * data)787 destroy_streams(void *data)
788 {
789 struct io_stream *stab = data;
790 struct io_stream *p;
791 for (p = stab; p < stab + nstreams; p++) {
792 close_stream(p);
793 free(p->buf);
794 }
795 free(stab);
796 }
797
798
799 #line 684
800
801 #line 684
802 static int IO_id;
803 #line 684 "io.bi"
804
805
806 int
_bi_io_fd(eval_environ_t env,int fd,int what)807 _bi_io_fd(eval_environ_t env, int fd, int what)
808 {
809 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
810 int descr;
811
812 if (!(fd >= 0 && fd < nstreams && what>=0 && what<=1))
813 #line 692
814 (
815 #line 692
816 env_throw_bi(env, mfe_range, NULL, _("invalid file descriptor"))
817 #line 692
818 )
819 #line 694
820 ;
821 descr = what == 0 ? IFD(iotab[fd]) : OFD(iotab[fd]);
822 if (!(descr >= 0))
823 #line 696
824 (
825 #line 696
826 env_throw_bi(env, mfe_range, NULL, _("invalid file descriptor"))
827 #line 696
828 )
829 #line 698
830 ;
831 return descr;
832 }
833
834
835 void
836 #line 703
bi_open(eval_environ_t env)837 bi_open(eval_environ_t env)
838 #line 703
839
840 #line 703
841
842 #line 703 "io.bi"
843 {
844 #line 703
845
846 #line 703
847
848 #line 703
849
850 #line 703
851 char * name;
852 #line 703
853
854 #line 703
855 get_string_arg(env, 0, &name);
856 #line 703
857
858 #line 703
859
860 #line 703
861 adjust_stack(env, 1);
862 #line 703
863
864 #line 703
865
866 #line 703
867 if (builtin_module_trace(BUILTIN_IDX_io))
868 #line 703
869 prog_trace(env, "open %s",name);;
870 #line 703
871
872 {
873 int i, rc;
874 int flags = 0;
875 int (*opf)(eval_environ_t env,
876 struct io_stream *, const char *, int) = open_file_stream;
877 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
878
879 for (i = 0; i < nstreams; i++) {
880 if (iotab[i].fd[0] == -1)
881 break;
882 }
883 if (!(i < nstreams))
884 #line 715
885 (
886 #line 715
887 env_throw_bi(env, mfe_failure, "open", _("no more files available"))
888 #line 715
889 )
890 #line 717
891 ;
892
893
894 #line 719
895
896 #line 719
897 mu_debug(debug_handle, MU_DEBUG_TRACE1,("opening stream %s", name));
898 iotab[i].name = mu_strdup(name);
899 iotab[i].delim = NULL;
900 if (*name == '>') {
901 flags |= O_RDWR|O_CREAT;
902 name++;
903 if (*name == '>') {
904 flags |= O_APPEND;
905 name++;
906 } else
907 flags |= O_TRUNC;
908 } else if (*name == '|') {
909 opf = open_program_stream;
910 flags = O_WRONLY;
911 name++;
912 if (*name == '&') {
913 flags = O_RDWR;
914 name++;
915 } else if (*name == '<') {
916 flags = O_RDONLY;
917 name++;
918 }
919 } else if (*name == '@') {
920 name++;
921 opf = open_inet_stream;
922 flags = O_RDWR;
923 } else
924 flags = O_RDONLY;
925
926 for (;*name && mu_isspace(*name); name++)
927 ;
928
929 rc = opf(env, &iotab[i], name, flags);
930
931 if (!(rc == 0))
932 #line 753
933 (
934 #line 753
935 env_throw_bi(env, mfe_failure, "open", _("cannot open stream %s: %s"),name,mu_strerror(rc))
936 #line 753
937 )
938 #line 756
939 ;
940
941 #line 757
942
943 #line 757
944 mu_debug(debug_handle, MU_DEBUG_TRACE1,("open(%s) = %d", name, i));
945
946 #line 758
947 do {
948 #line 758
949 push(env, (STKVAL)(mft_number)(i));
950 #line 758
951 goto endlab;
952 #line 758
953 } while (0);
954 }
955 endlab:
956 #line 760
957 env_function_cleanup_flush(env, NULL);
958 #line 760
959 return;
960 #line 760
961 }
962
963 void
964 #line 762
bi_spawn(eval_environ_t env)965 bi_spawn(eval_environ_t env)
966 #line 762
967
968 #line 762
969
970 #line 762 "io.bi"
971 {
972 #line 762
973
974 #line 762
975
976 #line 762
977 long __bi_argcnt;
978 #line 762
979 char * name;
980 #line 762
981 long fin;
982 #line 762
983 long fout;
984 #line 762
985 long ferr;
986 #line 762
987
988 #line 762
989 get_string_arg(env, 1, &name);
990 #line 762
991 get_numeric_arg(env, 2, &fin);
992 #line 762
993 get_numeric_arg(env, 3, &fout);
994 #line 762
995 get_numeric_arg(env, 4, &ferr);
996 #line 762
997
998 #line 762
999 get_numeric_arg(env, 0, &__bi_argcnt);
1000 #line 762
1001 adjust_stack(env, __bi_argcnt + 1);
1002 #line 762
1003
1004 #line 762
1005
1006 #line 762
1007 if (builtin_module_trace(BUILTIN_IDX_io))
1008 #line 762
1009 prog_trace(env, "spawn %s %lu %lu %lu",name, ((__bi_argcnt > 1) ? fin : 0), ((__bi_argcnt > 2) ? fout : 0), ((__bi_argcnt > 3) ? ferr : 0));;
1010
1011 {
1012 int i, rc;
1013 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1014 int ioe[3];
1015 int flags;
1016
1017 for (i = 0; i < nstreams; i++) {
1018 if (iotab[i].fd[0] == -1)
1019 break;
1020 }
1021 if (!(i < nstreams))
1022 #line 774
1023 (
1024 #line 774
1025 env_throw_bi(env, mfe_failure, "spawn", _("no more files available"))
1026 #line 774
1027 )
1028 #line 776
1029 ;
1030
1031
1032 #line 778
1033
1034 #line 778
1035 mu_debug(debug_handle, MU_DEBUG_TRACE1,("spawning %s", name));
1036 iotab[i].name = mu_strdup(name);
1037 iotab[i].delim = NULL;
1038
1039 flags = O_WRONLY;
1040 if (*name == '|')
1041 name++;
1042 if (*name == '&') {
1043 flags = O_RDWR;
1044 name++;
1045 } else if (*name == '<') {
1046 flags = O_RDONLY;
1047 name++;
1048 }
1049
1050 for (;*name && mu_isspace(*name); name++)
1051 ;
1052
1053 if ((__bi_argcnt > 1))
1054 ioe[0] = _bi_io_fd(env, ((__bi_argcnt > 1) ? fin : 0), 0);
1055 else
1056 ioe[0] = -1;
1057 if ((__bi_argcnt > 2))
1058 ioe[1] = _bi_io_fd(env, ((__bi_argcnt > 2) ? fout : 0), 1);
1059 else
1060 ioe[1] = -1;
1061 if ((__bi_argcnt > 3))
1062 ioe[2] = _bi_io_fd(env, ((__bi_argcnt > 2) ? fout : 0), 1);
1063 else
1064 ioe[2] = -1;
1065
1066 rc = open_program_stream_ioe(env, &iotab[i], name, flags, ioe);
1067
1068 if (!(rc == 0))
1069 #line 811
1070 (
1071 #line 811
1072 env_throw_bi(env, mfe_failure, "spawn", _("cannot open stream %s: %s"),name,mu_strerror(rc))
1073 #line 811
1074 )
1075 #line 814
1076 ;
1077
1078 #line 815
1079
1080 #line 815
1081 mu_debug(debug_handle, MU_DEBUG_TRACE1,("spawn(%s) = %d", name, i));
1082
1083 #line 816
1084 do {
1085 #line 816
1086 push(env, (STKVAL)(mft_number)(i));
1087 #line 816
1088 goto endlab;
1089 #line 816
1090 } while (0);
1091
1092 }
1093 endlab:
1094 #line 819
1095 env_function_cleanup_flush(env, NULL);
1096 #line 819
1097 return;
1098 #line 819
1099 }
1100
1101
1102 void
1103 #line 822
bi_tempfile(eval_environ_t env)1104 bi_tempfile(eval_environ_t env)
1105 #line 822
1106
1107 #line 822
1108
1109 #line 822 "io.bi"
1110 {
1111 #line 822
1112
1113 #line 822
1114
1115 #line 822
1116 long __bi_argcnt;
1117 #line 822
1118 char * MFL_DATASEG tempdir;
1119 #line 822
1120
1121 #line 822
1122 get_string_arg(env, 1, &tempdir);
1123 #line 822
1124
1125 #line 822
1126 get_numeric_arg(env, 0, &__bi_argcnt);
1127 #line 822
1128 adjust_stack(env, __bi_argcnt + 1);
1129 #line 822
1130
1131 #line 822
1132
1133 #line 822
1134 if (builtin_module_trace(BUILTIN_IDX_io))
1135 #line 822
1136 prog_trace(env, "tempfile %s",((__bi_argcnt > 0) ? tempdir : ""));;
1137 #line 822
1138
1139 {
1140 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1141 int i;
1142 char *dir = ((__bi_argcnt > 0) ? tempdir : "/tmp");
1143 size_t dirlen = strlen(dir);
1144 mode_t u;
1145 int fd;
1146 char *template;
1147 #define PATTERN "mfdXXXXXX"
1148
1149 for (i = 0; i < nstreams; i++) {
1150 if (iotab[i].fd[0] == -1)
1151 break;
1152 }
1153 if (!(i < nstreams))
1154 #line 837
1155 (
1156 #line 837
1157 env_throw_bi(env, mfe_failure, "tempfile", _("no more files available"))
1158 #line 837
1159 )
1160 #line 839
1161 ;
1162
1163
1164 while (dirlen > 0 && dir[dirlen-1] == '/')
1165 dirlen--;
1166
1167 template = mf_c_val(heap_tempspace(env, (dirlen ? dirlen + 1 : 0) +
1168 #line 845
1169 sizeof(PATTERN)), ptr);
1170 #line 847
1171 if (dirlen) {
1172 memcpy(template, dir, dirlen);
1173 template[dirlen++] = '/';
1174 }
1175 strcpy(template + dirlen, PATTERN);
1176 u = umask(077);
1177 fd = mkstemp(template);
1178 umask(u);
1179 if (!(fd >= 0))
1180 #line 855
1181 (
1182 #line 855
1183 env_throw_bi(env, mfe_failure, "tempfile", "mkstemp failed: %s",mu_strerror(errno))
1184 #line 855
1185 )
1186 #line 858
1187 ;
1188 unlink(template);
1189
1190 iotab[i].fd[0] = fd;
1191
1192
1193 #line 863
1194 do {
1195 #line 863
1196 push(env, (STKVAL)(mft_number)(i));
1197 #line 863
1198 goto endlab;
1199 #line 863
1200 } while (0);
1201 #undef PATTERN
1202 }
1203 endlab:
1204 #line 866
1205 env_function_cleanup_flush(env, NULL);
1206 #line 866
1207 return;
1208 #line 866
1209 }
1210
1211 void
1212 #line 868
bi_close(eval_environ_t env)1213 bi_close(eval_environ_t env)
1214 #line 868
1215
1216 #line 868
1217
1218 #line 868 "io.bi"
1219 {
1220 #line 868
1221
1222 #line 868
1223
1224 #line 868
1225
1226 #line 868
1227 long fd;
1228 #line 868
1229
1230 #line 868
1231 get_numeric_arg(env, 0, &fd);
1232 #line 868
1233
1234 #line 868
1235
1236 #line 868
1237 adjust_stack(env, 1);
1238 #line 868
1239
1240 #line 868
1241
1242 #line 868
1243 if (builtin_module_trace(BUILTIN_IDX_io))
1244 #line 868
1245 prog_trace(env, "close %lu",fd);;
1246 #line 868
1247
1248 {
1249 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1250
1251 if (!(fd >= 0 && fd < nstreams))
1252 #line 872
1253 (
1254 #line 872
1255 env_throw_bi(env, mfe_range, "close", _("invalid file descriptor"))
1256 #line 872
1257 )
1258 #line 874
1259 ;
1260 close_stream(&iotab[fd]);
1261 }
1262
1263 #line 877
1264 env_function_cleanup_flush(env, NULL);
1265 #line 877
1266 return;
1267 #line 877
1268 }
1269
1270 static struct builtin_const_trans shutdown_modes[] = {
1271 { _MFL_SHUT_RD, SHUT_RD },
1272 { _MFL_SHUT_WR, SHUT_WR },
1273 { _MFL_SHUT_RDWR, SHUT_RDWR }
1274 };
1275
1276 void
1277 #line 885
bi_shutdown(eval_environ_t env)1278 bi_shutdown(eval_environ_t env)
1279 #line 885
1280
1281 #line 885
1282
1283 #line 885 "io.bi"
1284 {
1285 #line 885
1286
1287 #line 885
1288
1289 #line 885
1290
1291 #line 885
1292 long fd;
1293 #line 885
1294 long how;
1295 #line 885
1296
1297 #line 885
1298 get_numeric_arg(env, 0, &fd);
1299 #line 885
1300 get_numeric_arg(env, 1, &how);
1301 #line 885
1302
1303 #line 885
1304
1305 #line 885
1306 adjust_stack(env, 2);
1307 #line 885
1308
1309 #line 885
1310
1311 #line 885
1312 if (builtin_module_trace(BUILTIN_IDX_io))
1313 #line 885
1314 prog_trace(env, "shutdown %lu %lu",fd, how);;
1315 #line 885
1316
1317 {
1318 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1319 struct io_stream *ioptr;
1320 int mode;
1321
1322 if (!(fd >= 0 && fd < nstreams))
1323 #line 891
1324 (
1325 #line 891
1326 env_throw_bi(env, mfe_range, "shutdown", _("invalid file descriptor"))
1327 #line 891
1328 )
1329 #line 893
1330 ;
1331 if (!(how >= 0 && how <= 2))
1332 #line 894
1333 (
1334 #line 894
1335 env_throw_bi(env, mfe_range, "shutdown", _("invalid file descriptor"))
1336 #line 894
1337 )
1338 #line 896
1339 ;
1340 if (!(_builtin_const_to_c(shutdown_modes,
1341 #line 897
1342 MU_ARRAY_SIZE(shutdown_modes),
1343 #line 897
1344 how,
1345 #line 897
1346 &mode) == 0))
1347 #line 897
1348 (
1349 #line 897
1350 env_throw_bi(env, mfe_failure, "shutdown", "bad shutdown mode")
1351 #line 897
1352 )
1353 #line 902
1354 ;
1355
1356 ioptr = &iotab[fd];
1357 if (ioptr->shutdown) {
1358 int rc = ioptr->shutdown(ioptr, mode);
1359 if (!(rc == 0))
1360 #line 907
1361 (
1362 #line 907
1363 env_throw_bi(env, mfe_io, "shutdown", "shutdown failed: %s",mu_strerror(rc))
1364 #line 907
1365 )
1366 #line 910
1367 ;
1368 } else if (how == 2)
1369 close_stream(ioptr);
1370 else if (ioptr->fd[how]) {
1371 close(ioptr->fd[how]);
1372 ioptr->fd[how] = -1;
1373 }
1374 }
1375
1376 #line 918
1377 env_function_cleanup_flush(env, NULL);
1378 #line 918
1379 return;
1380 #line 918
1381 }
1382
1383 void
1384 #line 920
bi_write(eval_environ_t env)1385 bi_write(eval_environ_t env)
1386 #line 920
1387
1388 #line 920
1389
1390 #line 920 "io.bi"
1391 {
1392 #line 920
1393
1394 #line 920
1395
1396 #line 920
1397 long __bi_argcnt;
1398 #line 920
1399 long fd;
1400 #line 920
1401 char * str;
1402 #line 920
1403 long n;
1404 #line 920
1405
1406 #line 920
1407 get_numeric_arg(env, 1, &fd);
1408 #line 920
1409 get_string_arg(env, 2, &str);
1410 #line 920
1411 get_numeric_arg(env, 3, &n);
1412 #line 920
1413
1414 #line 920
1415 get_numeric_arg(env, 0, &__bi_argcnt);
1416 #line 920
1417 adjust_stack(env, __bi_argcnt + 1);
1418 #line 920
1419
1420 #line 920
1421
1422 #line 920
1423 if (builtin_module_trace(BUILTIN_IDX_io))
1424 #line 920
1425 prog_trace(env, "write %lu %s %lu",fd, str, ((__bi_argcnt > 2) ? n : 0));;
1426 #line 920
1427
1428 {
1429 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1430 int rc;
1431
1432
1433 #line 925
1434
1435 #line 925
1436 mu_debug(debug_handle, MU_DEBUG_TRACE1,("writing %s to %lu", str, fd));
1437 if (!(fd >= 0 && fd < nstreams && OFD(iotab[fd]) != -1))
1438 #line 926
1439 (
1440 #line 926
1441 env_throw_bi(env, mfe_range, "write", _("invalid file descriptor"))
1442 #line 926
1443 )
1444 #line 928
1445 ;
1446 if (!(__bi_argcnt > 2))
1447 n = strlen (str);
1448 rc = write(OFD(iotab[fd]), str, n);
1449 if (!(n == rc))
1450 #line 932
1451 (
1452 #line 932
1453 env_throw_bi(env, mfe_io, "write", _("write error on %s: %s"),iotab[fd].name,mu_strerror(errno))
1454 #line 932
1455 )
1456 #line 935
1457 ;
1458 }
1459
1460 #line 937
1461 env_function_cleanup_flush(env, NULL);
1462 #line 937
1463 return;
1464 #line 937
1465 }
1466
1467
1468 void
1469 #line 940
bi_write_body(eval_environ_t env)1470 bi_write_body(eval_environ_t env)
1471 #line 940
1472
1473 #line 940
1474
1475 #line 940 "io.bi"
1476 {
1477 #line 940
1478
1479 #line 940
1480
1481 #line 940
1482
1483 #line 940
1484 long fd;
1485 #line 940
1486 void * str;
1487 #line 940
1488 long n;
1489 #line 940
1490
1491 #line 940
1492 get_numeric_arg(env, 0, &fd);
1493 #line 940
1494 get_pointer_arg(env, 1, &str);
1495 #line 940
1496 get_numeric_arg(env, 2, &n);
1497 #line 940
1498
1499 #line 940
1500
1501 #line 940
1502 adjust_stack(env, 3);
1503 #line 940
1504
1505 #line 940
1506
1507 #line 940
1508 if (builtin_module_trace(BUILTIN_IDX_io))
1509 #line 940
1510 prog_trace(env, "write_body %lu %p %lu",fd, str, n);;
1511 #line 940
1512
1513 {
1514 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1515 int rc;
1516
1517 if (!(fd >= 0 && fd < nstreams && OFD(iotab[fd]) != -1))
1518 #line 945
1519 (
1520 #line 945
1521 env_throw_bi(env, mfe_range, "write_body", _("invalid file descriptor"))
1522 #line 945
1523 )
1524 #line 947
1525 ;
1526 rc = write(OFD(iotab[fd]), str, n);
1527 if (!(n == rc))
1528 #line 949
1529 (
1530 #line 949
1531 env_throw_bi(env, mfe_io, "write_body", _("write error on %s: %s"),iotab[fd].name,mu_strerror(errno))
1532 #line 949
1533 )
1534 #line 952
1535 ;
1536 }
1537
1538 #line 954
1539 env_function_cleanup_flush(env, NULL);
1540 #line 954
1541 return;
1542 #line 954
1543 }
1544
1545 void
1546 #line 956
bi_read(eval_environ_t env)1547 bi_read(eval_environ_t env)
1548 #line 956
1549
1550 #line 956
1551
1552 #line 956 "io.bi"
1553 {
1554 #line 956
1555
1556 #line 956
1557
1558 #line 956
1559
1560 #line 956
1561 long fd;
1562 #line 956
1563 long size;
1564 #line 956
1565
1566 #line 956
1567 get_numeric_arg(env, 0, &fd);
1568 #line 956
1569 get_numeric_arg(env, 1, &size);
1570 #line 956
1571
1572 #line 956
1573
1574 #line 956
1575 adjust_stack(env, 2);
1576 #line 956
1577
1578 #line 956
1579
1580 #line 956
1581 if (builtin_module_trace(BUILTIN_IDX_io))
1582 #line 956
1583 prog_trace(env, "read %lu %lu",fd, size);;
1584 #line 956
1585
1586 {
1587 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1588 int rc;
1589 size_t off;
1590 char *s = (char*) env_data_ref(env, (off = heap_reserve(env, size + 1)));
1591
1592 if (!(fd >= 0 && fd < nstreams && IFD(iotab[fd]) != -1))
1593 #line 963
1594 (
1595 #line 963
1596 env_throw_bi(env, mfe_range, "read", _("invalid file descriptor"))
1597 #line 963
1598 )
1599 #line 965
1600 ;
1601
1602 rc = read(IFD(iotab[fd]), s, size);
1603 if (rc == 0)
1604 (
1605 #line 969
1606 env_throw_bi(env, mfe_eof, "read", _("EOF on %s"),iotab[fd].name)
1607 #line 969
1608 );
1609 #line 971
1610 if (!(rc == size))
1611 #line 971
1612 (
1613 #line 971
1614 env_throw_bi(env, mfe_io, "read", _("read error on %s: %s"),iotab[fd].name,mu_strerror(errno))
1615 #line 971
1616 )
1617 #line 974
1618 ;
1619 s[size] = 0;
1620
1621 #line 976
1622 do {
1623 #line 976
1624 push(env, (STKVAL) (mft_size) (off));
1625 #line 976
1626 goto endlab;
1627 #line 976
1628 } while (0);
1629 }
1630 endlab:
1631 #line 978
1632 env_function_cleanup_flush(env, NULL);
1633 #line 978
1634 return;
1635 #line 978
1636 }
1637
1638 void
1639 #line 980
bi_rewind(eval_environ_t env)1640 bi_rewind(eval_environ_t env)
1641 #line 980
1642
1643 #line 980
1644
1645 #line 980 "io.bi"
1646 {
1647 #line 980
1648
1649 #line 980
1650
1651 #line 980
1652
1653 #line 980
1654 long fd;
1655 #line 980
1656
1657 #line 980
1658 get_numeric_arg(env, 0, &fd);
1659 #line 980
1660
1661 #line 980
1662
1663 #line 980
1664 adjust_stack(env, 1);
1665 #line 980
1666
1667 #line 980
1668
1669 #line 980
1670 if (builtin_module_trace(BUILTIN_IDX_io))
1671 #line 980
1672 prog_trace(env, "rewind %lu",fd);;
1673 #line 980
1674
1675 {
1676 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1677
1678 if (!(fd >= 0 && fd < nstreams && IFD(iotab[fd]) != -1))
1679 #line 984
1680 (
1681 #line 984
1682 env_throw_bi(env, mfe_range, "rewind", _("invalid file descriptor"))
1683 #line 984
1684 )
1685 #line 986
1686 ;
1687 if (lseek(IFD(iotab[fd]), 0, SEEK_SET) == -1)
1688 (
1689 #line 988
1690 env_throw_bi(env, mfe_io, "rewind", "seek failed: %s",mu_strerror(errno))
1691 #line 988
1692 );
1693 #line 991
1694 }
1695
1696 #line 992
1697 env_function_cleanup_flush(env, NULL);
1698 #line 992
1699 return;
1700 #line 992
1701 }
1702
1703
1704 #define MINBUFSIZE 128
1705 #define MAXBUFSIZE 65535
1706
1707 void
1708 #line 998
bi_copy(eval_environ_t env)1709 bi_copy(eval_environ_t env)
1710 #line 998
1711
1712 #line 998
1713
1714 #line 998 "io.bi"
1715 {
1716 #line 998
1717
1718 #line 998
1719
1720 #line 998
1721
1722 #line 998
1723 long dst;
1724 #line 998
1725 long src;
1726 #line 998
1727
1728 #line 998
1729 get_numeric_arg(env, 0, &dst);
1730 #line 998
1731 get_numeric_arg(env, 1, &src);
1732 #line 998
1733
1734 #line 998
1735
1736 #line 998
1737 adjust_stack(env, 2);
1738 #line 998
1739
1740 #line 998
1741
1742 #line 998
1743 if (builtin_module_trace(BUILTIN_IDX_io))
1744 #line 998
1745 prog_trace(env, "copy %lu %lu",dst, src);;
1746 #line 998
1747
1748 {
1749 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1750 int ifd, ofd;
1751 char *buffer;
1752 size_t bufsize = MAXBUFSIZE;
1753 char bs[MINBUFSIZE];
1754 off_t cur, end;
1755 size_t total = 0;
1756 ssize_t rdbytes;
1757
1758 if (!(src >= 0 && src < nstreams && (ifd = IFD(iotab[src])) != -1))
1759 #line 1009
1760 (
1761 #line 1009
1762 env_throw_bi(env, mfe_range, "copy", _("invalid source file descriptor"))
1763 #line 1009
1764 )
1765 #line 1011
1766 ;
1767 if (!(dst >= 0 && dst < nstreams && (ofd = OFD(iotab[dst])) != -1))
1768 #line 1012
1769 (
1770 #line 1012
1771 env_throw_bi(env, mfe_range, "copy", _("invalid destination file descriptor"))
1772 #line 1012
1773 )
1774 #line 1014
1775 ;
1776
1777 cur = lseek (ifd, 0, SEEK_CUR);
1778 if (cur != -1) {
1779 end = lseek (ifd, 0, SEEK_END);
1780 if (end != -1) {
1781 if (end < MAXBUFSIZE)
1782 bufsize = end;
1783 lseek (ifd, cur, SEEK_SET);
1784 }
1785 }
1786
1787 for (; (buffer = malloc (bufsize)) == NULL; bufsize >>= 1)
1788 if (bufsize < MINBUFSIZE) {
1789 buffer = bs;
1790 bufsize = MINBUFSIZE;
1791 break;
1792 }
1793
1794 while ((rdbytes = read(ifd, buffer, bufsize)) > 0) {
1795 char *p = buffer;
1796 while (rdbytes) {
1797 ssize_t wrbytes = write(ofd, p, rdbytes);
1798 if (wrbytes == -1) {
1799 if (buffer != bs)
1800 free(buffer);
1801 (
1802 #line 1040
1803 env_throw_bi(env, mfe_io, "copy", "write error: %s",mu_strerror(errno))
1804 #line 1040
1805 );
1806 #line 1043
1807 } else if (wrbytes == 0) {
1808 if (buffer != bs)
1809 free(buffer);
1810 (
1811 #line 1046
1812 env_throw_bi(env, mfe_io, "copy", "short write")
1813 #line 1046
1814 );
1815 #line 1048
1816 }
1817 p += wrbytes;
1818 rdbytes -= wrbytes;
1819 total += wrbytes;
1820 }
1821 }
1822 if (buffer != bs)
1823 free(buffer);
1824
1825 #line 1056
1826 do {
1827 #line 1056
1828 push(env, (STKVAL)(mft_number)(total));
1829 #line 1056
1830 goto endlab;
1831 #line 1056
1832 } while (0);
1833 }
1834 endlab:
1835 #line 1058
1836 env_function_cleanup_flush(env, NULL);
1837 #line 1058
1838 return;
1839 #line 1058
1840 }
1841
1842 void
1843 #line 1060
bi_getdelim(eval_environ_t env)1844 bi_getdelim(eval_environ_t env)
1845 #line 1060
1846
1847 #line 1060
1848
1849 #line 1060 "io.bi"
1850 {
1851 #line 1060
1852
1853 #line 1060
1854
1855 #line 1060
1856
1857 #line 1060
1858 long fd;
1859 #line 1060
1860 char * MFL_DATASEG delim;
1861 #line 1060
1862
1863 #line 1060
1864 get_numeric_arg(env, 0, &fd);
1865 #line 1060
1866 get_string_arg(env, 1, &delim);
1867 #line 1060
1868
1869 #line 1060
1870
1871 #line 1060
1872 adjust_stack(env, 2);
1873 #line 1060
1874
1875 #line 1060
1876
1877 #line 1060
1878 if (builtin_module_trace(BUILTIN_IDX_io))
1879 #line 1060
1880 prog_trace(env, "getdelim %lu %s",fd, delim);;
1881 #line 1060
1882
1883 {
1884 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1885 struct io_stream *ioptr;
1886 int rc;
1887
1888 if (!(fd >= 0 && fd < nstreams && IFD(iotab[fd]) != -1))
1889 #line 1066
1890 (
1891 #line 1066
1892 env_throw_bi(env, mfe_range, "getdelim", _("invalid file descriptor"))
1893 #line 1066
1894 )
1895 #line 1068
1896 ;
1897 ioptr = &iotab[fd];
1898 rc = read_stream_delim(ioptr, delim);
1899 if (rc == 0)
1900 (
1901 #line 1072
1902 env_throw_bi(env, mfe_eof, "getdelim", _("EOF on %s"),ioptr->name)
1903 #line 1072
1904 );
1905 if (!(rc > 0))
1906 #line 1073
1907 (
1908 #line 1073
1909 env_throw_bi(env, mfe_io, "getdelim", _("read error on %s: %s"),ioptr->name,mu_strerror(errno))
1910 #line 1073
1911 )
1912 #line 1076
1913 ;
1914
1915 #line 1077
1916 do {
1917 #line 1077
1918 pushs(env, ioptr->buf);
1919 #line 1077
1920 goto endlab;
1921 #line 1077
1922 } while (0);
1923 }
1924 endlab:
1925 #line 1079
1926 env_function_cleanup_flush(env, NULL);
1927 #line 1079
1928 return;
1929 #line 1079
1930 }
1931
1932 void
1933 #line 1081
bi_getline(eval_environ_t env)1934 bi_getline(eval_environ_t env)
1935 #line 1081
1936
1937 #line 1081
1938
1939 #line 1081 "io.bi"
1940 {
1941 #line 1081
1942
1943 #line 1081
1944
1945 #line 1081
1946
1947 #line 1081
1948 long fd;
1949 #line 1081
1950
1951 #line 1081
1952 get_numeric_arg(env, 0, &fd);
1953 #line 1081
1954
1955 #line 1081
1956
1957 #line 1081
1958 adjust_stack(env, 1);
1959 #line 1081
1960
1961 #line 1081
1962
1963 #line 1081
1964 if (builtin_module_trace(BUILTIN_IDX_io))
1965 #line 1081
1966 prog_trace(env, "getline %lu",fd);;
1967 #line 1081
1968
1969 {
1970 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
1971 struct io_stream *ioptr;
1972 int rc;
1973
1974 if (!(fd >= 0 && fd < nstreams && IFD(iotab[fd]) != -1))
1975 #line 1087
1976 (
1977 #line 1087
1978 env_throw_bi(env, mfe_range, "getline", _("invalid file descriptor"))
1979 #line 1087
1980 )
1981 #line 1089
1982 ;
1983 ioptr = &iotab[fd];
1984 rc = read_stream_delim(ioptr, ioptr->delim ? ioptr->delim : "\n");
1985 if (rc == 0)
1986 (
1987 #line 1093
1988 env_throw_bi(env, mfe_eof, "getline", _("EOF on %s"),ioptr->name)
1989 #line 1093
1990 );
1991 #line 1095
1992 if (!(rc > 0))
1993 #line 1095
1994 (
1995 #line 1095
1996 env_throw_bi(env, mfe_io, "getline", _("read error on %s: %s"),ioptr->name,mu_strerror(errno))
1997 #line 1095
1998 )
1999 #line 1098
2000 ;
2001
2002 #line 1099
2003 do {
2004 #line 1099
2005 pushs(env, ioptr->buf);
2006 #line 1099
2007 goto endlab;
2008 #line 1099
2009 } while (0);
2010 }
2011 endlab:
2012 #line 1101
2013 env_function_cleanup_flush(env, NULL);
2014 #line 1101
2015 return;
2016 #line 1101
2017 }
2018
2019 void
2020 #line 1103
bi_fd_set_delimiter(eval_environ_t env)2021 bi_fd_set_delimiter(eval_environ_t env)
2022 #line 1103
2023
2024 #line 1103
2025
2026 #line 1103 "io.bi"
2027 {
2028 #line 1103
2029
2030 #line 1103
2031
2032 #line 1103
2033
2034 #line 1103
2035 long fd;
2036 #line 1103
2037 char * delim;
2038 #line 1103
2039
2040 #line 1103
2041 get_numeric_arg(env, 0, &fd);
2042 #line 1103
2043 get_string_arg(env, 1, &delim);
2044 #line 1103
2045
2046 #line 1103
2047
2048 #line 1103
2049 adjust_stack(env, 2);
2050 #line 1103
2051
2052 #line 1103
2053
2054 #line 1103
2055 if (builtin_module_trace(BUILTIN_IDX_io))
2056 #line 1103
2057 prog_trace(env, "fd_set_delimiter %lu %s",fd, delim);;
2058 #line 1103
2059
2060 {
2061 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
2062 struct io_stream *ioptr;
2063
2064 if (!(fd >= 0 && fd < nstreams && IFD(iotab[fd]) != -1))
2065 #line 1108
2066 (
2067 #line 1108
2068 env_throw_bi(env, mfe_range, "fd_set_delimiter", _("invalid file descriptor"))
2069 #line 1108
2070 )
2071 #line 1110
2072 ;
2073 ioptr = &iotab[fd];
2074 free(ioptr->delim);
2075 ioptr->delim = mu_strdup(delim);
2076 }
2077
2078 #line 1115
2079 env_function_cleanup_flush(env, NULL);
2080 #line 1115
2081 return;
2082 #line 1115
2083 }
2084
2085 void
2086 #line 1117
bi_fd_delimiter(eval_environ_t env)2087 bi_fd_delimiter(eval_environ_t env)
2088 #line 1117
2089
2090 #line 1117
2091
2092 #line 1117 "io.bi"
2093 {
2094 #line 1117
2095
2096 #line 1117
2097
2098 #line 1117
2099
2100 #line 1117
2101 long fd;
2102 #line 1117
2103 char * MFL_DATASEG delim;
2104 #line 1117
2105
2106 #line 1117
2107 get_numeric_arg(env, 0, &fd);
2108 #line 1117
2109 get_string_arg(env, 1, &delim);
2110 #line 1117
2111
2112 #line 1117
2113
2114 #line 1117
2115 adjust_stack(env, 2);
2116 #line 1117
2117
2118 #line 1117
2119
2120 #line 1117
2121 if (builtin_module_trace(BUILTIN_IDX_io))
2122 #line 1117
2123 prog_trace(env, "fd_delimiter %lu %s",fd, delim);;
2124 #line 1117
2125
2126 {
2127 struct io_stream *iotab = env_get_builtin_priv(env,IO_id);
2128 struct io_stream *ioptr;
2129
2130 if (!(fd >= 0 && fd < nstreams && IFD(iotab[fd]) != -1))
2131 #line 1122
2132 (
2133 #line 1122
2134 env_throw_bi(env, mfe_range, "fd_delimiter", _("invalid file descriptor"))
2135 #line 1122
2136 )
2137 #line 1124
2138 ;
2139 ioptr = &iotab[fd];
2140
2141 #line 1126
2142 do {
2143 #line 1126
2144 pushs(env, ioptr->delim ? ioptr->delim : "\n");
2145 #line 1126
2146 goto endlab;
2147 #line 1126
2148 } while (0);
2149 }
2150 endlab:
2151 #line 1128
2152 env_function_cleanup_flush(env, NULL);
2153 #line 1128
2154 return;
2155 #line 1128
2156 }
2157
2158
2159 #line 982 "../../src/builtin/snarf.m4"
2160
2161 #line 982
2162
2163 #line 982
2164
2165 #line 982
2166 void
2167 #line 982
io_init_builtin(void)2168 io_init_builtin(void)
2169 #line 982
2170 {
2171 #line 982
2172 debug_handle = mu_debug_register_category("bi_io");
2173 #line 982
2174
2175 #line 982
2176 #line 684 "io.bi"
2177 IO_id = builtin_priv_register(alloc_streams, destroy_streams,
2178 #line 684
2179 NULL);
2180 #line 703 "io.bi"
2181 va_builtin_install_ex("open", bi_open, 0, dtype_number, 1, 0, 0|0, dtype_string);
2182 #line 762 "io.bi"
2183 va_builtin_install_ex("spawn", bi_spawn, 0, dtype_number, 4, 3, 0|0, dtype_string, dtype_number, dtype_number, dtype_number);
2184 #line 822 "io.bi"
2185 va_builtin_install_ex("tempfile", bi_tempfile, 0, dtype_number, 1, 1, 0|0, dtype_string);
2186 #line 868 "io.bi"
2187 va_builtin_install_ex("close", bi_close, 0, dtype_unspecified, 1, 0, 0|0, dtype_number);
2188 #line 885 "io.bi"
2189 va_builtin_install_ex("shutdown", bi_shutdown, 0, dtype_unspecified, 2, 0, 0|0, dtype_number, dtype_number);
2190 #line 920 "io.bi"
2191 va_builtin_install_ex("write", bi_write, 0, dtype_unspecified, 3, 1, 0|0, dtype_number, dtype_string, dtype_number);
2192 #line 940 "io.bi"
2193 va_builtin_install_ex("write_body", bi_write_body, STATMASK(smtp_state_body), dtype_unspecified, 3, 0, 0|0, dtype_number, dtype_pointer, dtype_number);
2194 #line 956 "io.bi"
2195 va_builtin_install_ex("read", bi_read, 0, dtype_string, 2, 0, 0|0, dtype_number, dtype_number);
2196 #line 980 "io.bi"
2197 va_builtin_install_ex("rewind", bi_rewind, 0, dtype_unspecified, 1, 0, 0|0, dtype_number);
2198 #line 998 "io.bi"
2199 va_builtin_install_ex("copy", bi_copy, 0, dtype_number, 2, 0, 0|0, dtype_number, dtype_number);
2200 #line 1060 "io.bi"
2201 va_builtin_install_ex("getdelim", bi_getdelim, 0, dtype_string, 2, 0, 0|0, dtype_number, dtype_string);
2202 #line 1081 "io.bi"
2203 va_builtin_install_ex("getline", bi_getline, 0, dtype_string, 1, 0, 0|0, dtype_number);
2204 #line 1103 "io.bi"
2205 va_builtin_install_ex("fd_set_delimiter", bi_fd_set_delimiter, 0, dtype_unspecified, 2, 0, 0|0, dtype_number, dtype_string);
2206 #line 1117 "io.bi"
2207 va_builtin_install_ex("fd_delimiter", bi_fd_delimiter, 0, dtype_string, 2, 0, 0|0, dtype_number, dtype_string);
2208
2209 #line 982 "../../src/builtin/snarf.m4"
2210
2211 #line 982
2212 mf_add_runtime_params(io_cfg_param);
2213 #line 982
2214
2215 #line 982
2216 }
2217 #line 982 "../../src/builtin/snarf.m4"
2218
2219