Annotation of OpenXM_contrib/gnuplot/vms.c, Revision 1.1
1.1 ! maekawa 1: #ifndef lint
! 2: static char *RCSid = "$Id: vms.c,v 1.5 1998/06/18 14:55:22 ddenholm Exp $";
! 3: #endif
! 4:
! 5: /* GNUPLOT - vms.c */
! 6:
! 7: /*[
! 8: * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
! 9: *
! 10: * Permission to use, copy, and distribute this software and its
! 11: * documentation for any purpose with or without fee is hereby granted,
! 12: * provided that the above copyright notice appear in all copies and
! 13: * that both that copyright notice and this permission notice appear
! 14: * in supporting documentation.
! 15: *
! 16: * Permission to modify the software is granted, but not the right to
! 17: * distribute the complete modified source code. Modifications are to
! 18: * be distributed as patches to the released version. Permission to
! 19: * distribute binaries produced by compiling modified sources is granted,
! 20: * provided you
! 21: * 1. distribute the corresponding source modifications from the
! 22: * released version in the form of a patch file along with the binaries,
! 23: * 2. add special version identification to distinguish your version
! 24: * in addition to the base release version number,
! 25: * 3. provide your name and address as the primary contact for the
! 26: * support of your modified version, and
! 27: * 4. retain our contact information in regard to use of the base
! 28: * software.
! 29: * Permission to distribute the released version of the source code along
! 30: * with corresponding source modifications in the form of a patch file is
! 31: * granted with same provisions 2 through 4 for binary distributions.
! 32: *
! 33: * This software is provided "as is" without express or implied warranty
! 34: * to the extent permitted by applicable law.
! 35: ]*/
! 36:
! 37: /* drop in popen() / pclose() for VMS
! 38: * (originally written by drd for port of perl to vms)
! 39: */
! 40:
! 41: #include "plot.h" /* for the prototypes */
! 42: #include "stdfn.h"
! 43:
! 44: static int something_in_this_file;
! 45:
! 46: #ifdef PIPES
! 47:
! 48: /* (to aid porting) - how are errors dealt with */
! 49:
! 50: #define ERROR(msg) { fprintf(stderr, "%s\nFile %s line %d\n", msg, __FILE__, __LINE__); }
! 51: #define FATAL(msg) { fprintf(stderr, "%s\nFile %s line %d\n", msg, __FILE__, __LINE__); exit(EXIT_FAILURE); }
! 52:
! 53:
! 54: #include <dvidef.h>
! 55: #include <syidef.h>
! 56: #include <jpidef.h>
! 57: #include <ssdef.h>
! 58: #include <descrip.h>
! 59:
! 60: #ifdef __DECC /* DECC does not automatically search */
! 61: #include <lib$routines.h>
! 62: #include <starlet.h> /* for the sys$... routines */
! 63: #endif /* __DECC */
! 64:
! 65: #ifndef EXIT_FAILURE /* not in older VAXC <stdlib.h> */
! 66: #define EXIT_FAILURE 0x10000002 /* (STS$K_ERROR | STS$M_INHIB_MSG */
! 67: #endif
! 68:
! 69: #define _cksts(call) \
! 70: if (!(sts=(call))&1) FATAL("Internal error") else {}
! 71:
! 72: static void
! 73: create_mbx(unsigned short int *chan, struct dsc$descriptor_s *namdsc)
! 74: {
! 75: static unsigned long int mbxbufsiz;
! 76: long int syiitm = SYI$_MAXBUF, dviitm = DVI$_DEVNAM;
! 77: unsigned long sts; /* for _cksts */
! 78:
! 79: if (!mbxbufsiz) {
! 80: /*
! 81: * Get the SYSGEN parameter MAXBUF, and the smaller of it and the
! 82: * preprocessor consant BUFSIZ from stdio.h as the size of the
! 83: * 'pipe' mailbox.
! 84: */
! 85:
! 86: _cksts(lib$getsyi(&syiitm, &mbxbufsiz, 0, 0, 0, 0));
! 87: if (mbxbufsiz > BUFSIZ) mbxbufsiz = BUFSIZ;
! 88: }
! 89: _cksts(sys$crembx(0,chan,mbxbufsiz,mbxbufsiz,0,0,0));
! 90:
! 91: _cksts(lib$getdvi(&dviitm, chan, NULL, NULL, namdsc, &namdsc->dsc$w_length));
! 92: namdsc->dsc$a_pointer[namdsc->dsc$w_length] = '\0';
! 93:
! 94: } /* end of create_mbx() */
! 95:
! 96: struct pipe_details
! 97: {
! 98: struct pipe_details *next;
! 99: FILE *fp;
! 100: int pid;
! 101: unsigned long int completion;
! 102: };
! 103:
! 104: static struct pipe_details *open_pipes = NULL;
! 105: static $DESCRIPTOR(nl_desc, "NL:");
! 106: static int waitpid_asleep = 0;
! 107:
! 108: static void
! 109: popen_completion_ast(unsigned long int unused)
! 110: {
! 111: if (waitpid_asleep) {
! 112: waitpid_asleep = 0;
! 113: sys$wake(0,0);
! 114: }
! 115: }
! 116:
! 117: FILE *
! 118: popen(char *cmd, char *mode)
! 119: {
! 120: static char mbxname[64];
! 121: unsigned short int chan;
! 122: unsigned long int flags=1; /* nowait - gnu c doesn't allow &1 */
! 123: struct pipe_details *info;
! 124: struct dsc$descriptor_s namdsc = {sizeof mbxname, DSC$K_DTYPE_T,
! 125: DSC$K_CLASS_S, mbxname},
! 126: cmddsc = {0, DSC$K_DTYPE_T,
! 127: DSC$K_CLASS_S, 0};
! 128: unsigned long sts;
! 129:
! 130: if (!(info=malloc(sizeof(struct pipe_details))))
! 131: {
! 132: ERROR("Cannot malloc space");
! 133: return NULL;
! 134: }
! 135:
! 136: info->completion=0; /* I assume this will remain 0 until terminates */
! 137:
! 138: /* create mailbox */
! 139: create_mbx(&chan,&namdsc);
! 140:
! 141: /* open a FILE* onto it */
! 142: info->fp=fopen(mbxname, mode);
! 143:
! 144: /* give up other channel onto it */
! 145: _cksts(sys$dassgn(chan));
! 146:
! 147: if (!info->fp)
! 148: return NULL;
! 149:
! 150: cmddsc.dsc$w_length=strlen(cmd);
! 151: cmddsc.dsc$a_pointer=cmd;
! 152:
! 153: if (strcmp(mode,"r")==0) {
! 154: _cksts(lib$spawn(&cmddsc, &nl_desc, &namdsc, &flags,
! 155: 0 /* name */, &info->pid, &info->completion,
! 156: 0, popen_completion_ast,0,0,0,0));
! 157: }
! 158: else {
! 159: _cksts(lib$spawn(&cmddsc, &namdsc, 0 /* sys$output */, &flags,
! 160: 0 /* name */, &info->pid, &info->completion));
! 161: }
! 162:
! 163: info->next=open_pipes; /* prepend to list */
! 164: open_pipes=info;
! 165:
! 166: return info->fp;
! 167: }
! 168:
! 169: int pclose(FILE *fp)
! 170: {
! 171: struct pipe_details *info, *last = NULL;
! 172: unsigned long int abort = SS$_TIMEOUT, retsts;
! 173: unsigned long sts;
! 174:
! 175: for (info = open_pipes; info != NULL; last = info, info = info->next)
! 176: if (info->fp == fp) break;
! 177:
! 178: if (info == NULL)
! 179: /* get here => no such pipe open */
! 180: FATAL("pclose() - no such pipe open ???");
! 181:
! 182: if (!info->completion) { /* Tap them gently on the shoulder . . .*/
! 183: _cksts(sys$forcex(&info->pid,0,&abort));
! 184: sleep(1);
! 185: }
! 186: if (!info->completion) /* We tried to be nice . . . */
! 187: _cksts(sys$delprc(&info->pid));
! 188:
! 189: fclose(info->fp);
! 190: /* remove from list of open pipes */
! 191: if (last) last->next = info->next;
! 192: else open_pipes = info->next;
! 193: retsts = info->completion;
! 194: free(info);
! 195:
! 196: return retsts;
! 197: } /* end of pclose() */
! 198:
! 199:
! 200: /* sort-of waitpid; use only with popen() */
! 201: /*{{{unsigned long int waitpid(unsigned long int pid, int *statusp, int flags)*/
! 202: unsigned long int
! 203: waitpid(unsigned long int pid, int *statusp, int flags)
! 204: {
! 205: struct pipe_details *info;
! 206: unsigned long int abort = SS$_TIMEOUT;
! 207: unsigned long sts;
! 208:
! 209: for (info = open_pipes; info != NULL; info = info->next)
! 210: if (info->pid == pid) break;
! 211:
! 212: if (info != NULL) { /* we know about this child */
! 213: while (!info->completion) {
! 214: waitpid_asleep = 1;
! 215: sys$hiber();
! 216: }
! 217:
! 218: *statusp = info->completion;
! 219: return pid;
! 220: }
! 221: else { /* we haven't heard of this child */
! 222: $DESCRIPTOR(intdsc,"0 00:00:01");
! 223: unsigned long int ownercode = JPI$_OWNER, ownerpid, mypid;
! 224: unsigned long int interval[2];
! 225:
! 226: _cksts(lib$getjpi(&ownercode,&pid,0,&ownerpid,0,0));
! 227: _cksts(lib$getjpi(&ownercode,0,0,&mypid,0,0));
! 228: if (ownerpid != mypid)
! 229: FATAL("pid not a child");
! 230:
! 231: _cksts(sys$bintim(&intdsc,interval));
! 232: while ((sts=lib$getjpi(&ownercode,&pid,0,&ownerpid,0,0)) & 1) {
! 233: _cksts(sys$schdwk(0,0,interval,0));
! 234: _cksts(sys$hiber());
! 235: }
! 236: _cksts(sts);
! 237:
! 238: /* There's no easy way to find the termination status a child we're
! 239: * not aware of beforehand. If we're really interested in the future,
! 240: * we can go looking for a termination mailbox, or chase after the
! 241: * accounting record for the process.
! 242: */
! 243: *statusp = 0;
! 244: return pid;
! 245: }
! 246:
! 247: } /* end of waitpid() */
! 248:
! 249: #endif /* PIPES */
! 250:
! 251:
! 252: /* vax c doesn't come with strftime - watch out for redefn of RCSid */
! 253: #ifdef VAXCRTL
! 254: # define RCSid RCSid2
! 255: # include "strftime.c"
! 256: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>