perl 4.0 patch 14: patch #11, continued
[p5sagit/p5-mst-13.2.git] / usersub.c
1 /* $Header: usersub.c,v 4.0 91/03/20 01:55:56 lwall Locked $
2  *
3  *  This file contains stubs for routines that the user may define to
4  *  set up glue routines for C libraries or to decrypt encrypted scripts
5  *  for execution.
6  *
7  * $Log:        usersub.c,v $
8  * Revision 4.0  91/03/20  01:55:56  lwall
9  * 4.0 baseline.
10  * 
11  */
12
13 #include "EXTERN.h"
14 #include "perl.h"
15
16 userinit()
17 {
18     return 0;
19 }
20
21 /*
22  * The following is supplied by John MacDonald as a means of decrypting
23  * and executing (presumably proprietary) scripts that have been encrypted
24  * by a (presumably secret) method.  The idea is that you supply your own
25  * routine in place of cryptfilter (which is purposefully a very weak
26  * encryption).  If an encrypted script is detected, a process is forked
27  * off to run the cryptfilter routine as input to perl.
28  */
29
30 #ifdef CRYPTSCRIPT
31
32 #include <signal.h>
33 #ifdef I_VFORK
34 #include <vfork.h>
35 #endif
36
37 #define CRYPT_MAGIC_1   0xfb
38 #define CRYPT_MAGIC_2   0xf1
39
40 cryptfilter( fil )
41 FILE *  fil;
42 {
43     int    ch;
44
45     while( (ch = getc( fil )) != EOF ) {
46         putchar( (ch ^ 0x80) );
47     }
48 }
49
50 #ifndef MSDOS
51 static FILE     *lastpipefile;
52 static int      pipepid;
53
54 #ifdef VOIDSIG
55 #  define       VOID    void
56 #else
57 #  define       VOID    int
58 #endif
59
60 FILE *
61 mypfiopen(fil,func)             /* open a pipe to function call for input */
62 FILE    *fil;
63 VOID    (*func)();
64 {
65     int p[2];
66     STR *str;
67
68     if (pipe(p) < 0) {
69         fclose( fil );
70         fatal("Can't get pipe for decrypt");
71     }
72
73     /* make sure that the child doesn't get anything extra */
74     fflush(stdout);
75     fflush(stderr);
76
77     while ((pipepid = fork()) < 0) {
78         if (errno != EAGAIN) {
79             close(p[0]);
80             close(p[1]);
81             fclose( fil );
82             fatal("Can't fork for decrypt");
83         }
84         sleep(5);
85     }
86     if (pipepid == 0) {
87         close(p[0]);
88         if (p[1] != 1) {
89             dup2(p[1], 1);
90             close(p[1]);
91         }
92         (*func)(fil);
93         fflush(stdout);
94         fflush(stderr);
95         _exit(0);
96     }
97     close(p[1]);
98     fclose(fil);
99     str = afetch(fdpid,p[0],TRUE);
100     str->str_u.str_useful = pipepid;
101     return fdopen(p[0], "r");
102 }
103
104 cryptswitch()
105 {
106     int ch;
107 #ifdef STDSTDIO
108     /* cheat on stdio if possible */
109     if (rsfp->_cnt > 0 && (*rsfp->_ptr & 0xff) != CRYPT_MAGIC_1)
110         return;
111 #endif
112     ch = getc(rsfp);
113     if (ch == CRYPT_MAGIC_1) {
114         if (getc(rsfp) == CRYPT_MAGIC_2) {
115             rsfp = mypfiopen( rsfp, cryptfilter );
116             preprocess = 1;     /* force call to pclose when done */
117         }
118         else
119             fatal( "bad encryption format" );
120     }
121     else
122         ungetc(ch,rsfp);
123 }
124
125 FILE *
126 cryptopen(cmd)          /* open a (possibly encrypted) program for input */
127 char    *cmd;
128 {
129     FILE        *fil = fopen( cmd, "r" );
130
131     lastpipefile = Nullfp;
132     pipepid = 0;
133
134     if( fil ) {
135         int     ch = getc( fil );
136         int     lines = 0;
137         int     chars = 0;
138
139         /* Search for the magic cookie that starts the encrypted script,
140         ** while still allowing a few lines of unencrypted text to let
141         ** '#!' and the nih hack both continue to work.  (These lines
142         ** will end up being ignored.)
143         */
144         while( ch != CRYPT_MAGIC_1 && ch != EOF && lines < 5 && chars < 300 ) {
145             if( ch == '\n' )
146                 ++lines;
147             ch = getc( fil );
148             ++chars;
149         }
150
151         if( ch == CRYPT_MAGIC_1 ) {
152             if( (ch = getc( fil ) ) == CRYPT_MAGIC_2 ) {
153                 if( perldb ) fatal("can't debug an encrypted script");
154                 /* we found it, decrypt the rest of the file */
155                 fil = mypfiopen( fil, cryptfilter );
156                 return( lastpipefile = fil );
157             } else
158                 /* if its got MAGIC 1 without MAGIC 2, too bad */
159                 fatal( "bad encryption format" );
160         }
161
162         /* this file is not encrypted - rewind and process it normally */
163         rewind( fil );
164     }
165
166     return( fil );
167 }
168
169 VOID
170 cryptclose(fil)
171 FILE    *fil;
172 {
173     if( fil == Nullfp )
174         return;
175
176     if( fil == lastpipefile )
177         mypclose( fil );
178     else
179         fclose( fil );
180 }
181 #endif /* !MSDOS */
182
183 #endif /* CRYPTSCRIPT */