~ubuntu-branches/ubuntu/raring/less/raring-proposed

« back to all changes in this revision

Viewing changes to lsystem.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Schoepf
  • Date: 2002-04-04 16:43:52 UTC
  • Revision ID: james.westby@ubuntu.com-20020404164352-qldq048yoc7x5sd5
Tags: upstream-374
ImportĀ upstreamĀ versionĀ 374

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1984-2000  Mark Nudelman
 
3
 *
 
4
 * You may distribute under the terms of either the GNU General Public
 
5
 * License or the Less License, as specified in the README file.
 
6
 *
 
7
 * For more information about less, or for information on how to 
 
8
 * contact the author, see the README file.
 
9
 */
 
10
 
 
11
 
 
12
/*
 
13
 * Routines to execute other programs.
 
14
 * Necessarily very OS dependent.
 
15
 */
 
16
 
 
17
#include "less.h"
 
18
#include <signal.h>
 
19
#include "position.h"
 
20
 
 
21
#if MSDOS_COMPILER
 
22
#include <dos.h>
 
23
#ifdef _MSC_VER
 
24
#include <direct.h>
 
25
#define setdisk(n) _chdrive((n)+1)
 
26
#else
 
27
#include <dir.h>
 
28
#endif
 
29
#endif
 
30
 
 
31
extern int screen_trashed;
 
32
extern IFILE curr_ifile;
 
33
 
 
34
 
 
35
#if HAVE_SYSTEM
 
36
 
 
37
/*
 
38
 * Pass the specified command to a shell to be executed.
 
39
 * Like plain "system()", but handles resetting terminal modes, etc.
 
40
 */
 
41
        public void
 
42
lsystem(cmd, donemsg)
 
43
        char *cmd;
 
44
        char *donemsg;
 
45
{
 
46
        register int inp;
 
47
#if HAVE_SHELL
 
48
        register char *shell;
 
49
        register char *p;
 
50
#endif
 
51
        IFILE save_ifile;
 
52
#if MSDOS_COMPILER
 
53
        char cwd[FILENAME_MAX+1];
 
54
#endif
 
55
 
 
56
        /*
 
57
         * Print the command which is to be executed,
 
58
         * unless the command starts with a "-".
 
59
         */
 
60
        if (cmd[0] == '-')
 
61
                cmd++;
 
62
        else
 
63
        {
 
64
                clear_bot();
 
65
                putstr("!");
 
66
                putstr(cmd);
 
67
                putstr("\n");
 
68
        }
 
69
 
 
70
#if MSDOS_COMPILER
 
71
        /*
 
72
         * Working directory is global on MSDOS.
 
73
         * The child might change the working directory, so we
 
74
         * must save and restore CWD across calls to "system",
 
75
         * or else we won't find our file when we return and
 
76
         * try to "reedit_ifile" it.
 
77
         */
 
78
        getcwd(cwd, FILENAME_MAX);
 
79
#endif
 
80
 
 
81
        /*
 
82
         * Close the current input file.
 
83
         */
 
84
        save_ifile = save_curr_ifile();
 
85
        (void) edit_ifile(NULL_IFILE);
 
86
 
 
87
        /*
 
88
         * De-initialize the terminal and take out of raw mode.
 
89
         */
 
90
        deinit();
 
91
        flush();        /* Make sure the deinit chars get out */
 
92
        raw_mode(0);
 
93
#if MSDOS_COMPILER==WIN32C
 
94
        close_getchr();
 
95
#endif
 
96
 
 
97
        /*
 
98
         * Restore signals to their defaults.
 
99
         */
 
100
        init_signals(0);
 
101
 
 
102
#if HAVE_DUP
 
103
        /*
 
104
         * Force standard input to be the user's terminal
 
105
         * (the normal standard input), even if less's standard input 
 
106
         * is coming from a pipe.
 
107
         */
 
108
        inp = dup(0);
 
109
        close(0);
 
110
#if OS2
 
111
        /* The __open() system call translates "/dev/tty" to "con". */
 
112
        if (__open("/dev/tty", OPEN_READ) < 0)
 
113
#else
 
114
        if (open("/dev/tty", OPEN_READ) < 0)
 
115
#endif
 
116
                dup(inp);
 
117
#endif
 
118
 
 
119
        /*
 
120
         * Pass the command to the system to be executed.
 
121
         * If we have a SHELL environment variable, use
 
122
         * <$SHELL -c "command"> instead of just <command>.
 
123
         * If the command is empty, just invoke a shell.
 
124
         */
 
125
#if HAVE_SHELL
 
126
        p = NULL;
 
127
        if ((shell = lgetenv("SHELL")) != NULL && *shell != '\0')
 
128
        {
 
129
                if (*cmd == '\0')
 
130
                        p = save(shell);
 
131
                else
 
132
                {
 
133
                        char *esccmd = shell_quote(cmd);
 
134
                        if (esccmd != NULL)
 
135
                        {
 
136
                                p = (char *) ecalloc(strlen(shell) +
 
137
                                        strlen(esccmd) + 5, sizeof(char));
 
138
                                sprintf(p, "%s %s %s", shell, shell_coption(), esccmd);
 
139
                                free(esccmd);
 
140
                        }
 
141
                }
 
142
        }
 
143
        if (p == NULL)
 
144
        {
 
145
                if (*cmd == '\0')
 
146
                        p = save("sh");
 
147
                else
 
148
                        p = save(cmd);
 
149
        }
 
150
        system(p);
 
151
        free(p);
 
152
#else
 
153
#if MSDOS_COMPILER==DJGPPC
 
154
        /*
 
155
         * Make stdin of the child be in cooked mode.
 
156
         */
 
157
        setmode(0, O_TEXT);
 
158
        /*
 
159
         * We don't need to catch signals of the child (it
 
160
         * also makes trouble with some DPMI servers).
 
161
         */
 
162
        __djgpp_exception_toggle();
 
163
        system(cmd);
 
164
        __djgpp_exception_toggle();
 
165
#else
 
166
        system(cmd);
 
167
#endif
 
168
#endif
 
169
 
 
170
#if HAVE_DUP
 
171
        /*
 
172
         * Restore standard input, reset signals, raw mode, etc.
 
173
         */
 
174
        close(0);
 
175
        dup(inp);
 
176
        close(inp);
 
177
#endif
 
178
 
 
179
#if MSDOS_COMPILER==WIN32C
 
180
        open_getchr();
 
181
#endif
 
182
        init_signals(1);
 
183
        raw_mode(1);
 
184
        if (donemsg != NULL)
 
185
        {
 
186
                putstr(donemsg);
 
187
                putstr("  (press RETURN)");
 
188
                get_return();
 
189
                putchr('\n');
 
190
                flush();
 
191
        }
 
192
        init();
 
193
        screen_trashed = 1;
 
194
 
 
195
#if MSDOS_COMPILER
 
196
        /*
 
197
         * Restore the previous directory (possibly
 
198
         * changed by the child program we just ran).
 
199
         */
 
200
        chdir(cwd);
 
201
#if MSDOS_COMPILER != DJGPPC
 
202
        /*
 
203
         * Some versions of chdir() don't change to the drive
 
204
         * which is part of CWD.  (DJGPP does this in chdir.)
 
205
         */
 
206
        if (cwd[1] == ':')
 
207
        {
 
208
                if (cwd[0] >= 'a' && cwd[0] <= 'z')
 
209
                        setdisk(cwd[0] - 'a');
 
210
                else if (cwd[0] >= 'A' && cwd[0] <= 'Z')
 
211
                        setdisk(cwd[0] - 'A');
 
212
        }
 
213
#endif
 
214
#endif
 
215
 
 
216
        /*
 
217
         * Reopen the current input file.
 
218
         */
 
219
        reedit_ifile(save_ifile);
 
220
 
 
221
#if defined(SIGWINCH) || defined(SIGWIND)
 
222
        /*
 
223
         * Since we were ignoring window change signals while we executed
 
224
         * the system command, we must assume the window changed.
 
225
         * Warning: this leaves a signal pending (in "sigs"),
 
226
         * so psignals() should be called soon after lsystem().
 
227
         */
 
228
        winch(0);
 
229
#endif
 
230
}
 
231
 
 
232
#endif
 
233
 
 
234
#if PIPEC
 
235
 
 
236
/*
 
237
 * Pipe a section of the input file into the given shell command.
 
238
 * The section to be piped is the section "between" the current
 
239
 * position and the position marked by the given letter.
 
240
 *
 
241
 * If the mark is after the current screen, the section between
 
242
 * the top line displayed and the mark is piped.
 
243
 * If the mark is before the current screen, the section between
 
244
 * the mark and the bottom line displayed is piped.
 
245
 * If the mark is on the current screen, or if the mark is ".",
 
246
 * the whole current screen is piped.
 
247
 */
 
248
        public int
 
249
pipe_mark(c, cmd)
 
250
        int c;
 
251
        char *cmd;
 
252
{
 
253
        POSITION mpos, tpos, bpos;
 
254
 
 
255
        /*
 
256
         * mpos = the marked position.
 
257
         * tpos = top of screen.
 
258
         * bpos = bottom of screen.
 
259
         */
 
260
        mpos = markpos(c);
 
261
        if (mpos == NULL_POSITION)
 
262
                return (-1);
 
263
        tpos = position(TOP);
 
264
        if (tpos == NULL_POSITION)
 
265
                tpos = ch_zero();
 
266
        bpos = position(BOTTOM);
 
267
 
 
268
        if (c == '.') 
 
269
                return (pipe_data(cmd, tpos, bpos));
 
270
        else if (mpos <= tpos)
 
271
                return (pipe_data(cmd, mpos, bpos));
 
272
        else if (bpos == NULL_POSITION)
 
273
                return (pipe_data(cmd, tpos, bpos));
 
274
        else
 
275
                return (pipe_data(cmd, tpos, mpos));
 
276
}
 
277
 
 
278
/*
 
279
 * Create a pipe to the given shell command.
 
280
 * Feed it the file contents between the positions spos and epos.
 
281
 */
 
282
        public int
 
283
pipe_data(cmd, spos, epos)
 
284
        char *cmd;
 
285
        POSITION spos;
 
286
        POSITION epos;
 
287
{
 
288
        register FILE *f;
 
289
        register int c;
 
290
        extern FILE *popen();
 
291
 
 
292
        /*
 
293
         * This is structured much like lsystem().
 
294
         * Since we're running a shell program, we must be careful
 
295
         * to perform the necessary deinitialization before running
 
296
         * the command, and reinitialization after it.
 
297
         */
 
298
        if (ch_seek(spos) != 0)
 
299
        {
 
300
                error("Cannot seek to start position", NULL_PARG);
 
301
                return (-1);
 
302
        }
 
303
 
 
304
        if ((f = popen(cmd, "w")) == NULL)
 
305
        {
 
306
                error("Cannot create pipe", NULL_PARG);
 
307
                return (-1);
 
308
        }
 
309
        clear_bot();
 
310
        putstr("!");
 
311
        putstr(cmd);
 
312
        putstr("\n");
 
313
 
 
314
        deinit();
 
315
        flush();
 
316
        raw_mode(0);
 
317
        init_signals(0);
 
318
#if MSDOS_COMPILER==WIN32C
 
319
        close_getchr();
 
320
#endif
 
321
#ifdef SIGPIPE
 
322
        LSIGNAL(SIGPIPE, SIG_IGN);
 
323
#endif
 
324
 
 
325
        c = EOI;
 
326
        while (epos == NULL_POSITION || spos++ <= epos)
 
327
        {
 
328
                /*
 
329
                 * Read a character from the file and give it to the pipe.
 
330
                 */
 
331
                c = ch_forw_get();
 
332
                if (c == EOI)
 
333
                        break;
 
334
                if (putc(c, f) == EOF)
 
335
                        break;
 
336
        }
 
337
 
 
338
        /*
 
339
         * Finish up the last line.
 
340
         */
 
341
        while (c != '\n' && c != EOI ) 
 
342
        {
 
343
                c = ch_forw_get();
 
344
                if (c == EOI)
 
345
                        break;
 
346
                if (putc(c, f) == EOF)
 
347
                        break;
 
348
        }
 
349
 
 
350
        pclose(f);
 
351
 
 
352
#ifdef SIGPIPE
 
353
        LSIGNAL(SIGPIPE, SIG_DFL);
 
354
#endif
 
355
#if MSDOS_COMPILER==WIN32C
 
356
        open_getchr();
 
357
#endif
 
358
        init_signals(1);
 
359
        raw_mode(1);
 
360
        init();
 
361
        screen_trashed = 1;
 
362
#if defined(SIGWINCH) || defined(SIGWIND)
 
363
        /* {{ Probably don't need this here. }} */
 
364
        winch(0);
 
365
#endif
 
366
        return (0);
 
367
}
 
368
 
 
369
#endif
 
370
 
 
371
#ifdef _OSK
 
372
/*
 
373
 *    Popen, and Pclose, for OS-9.
 
374
 *
 
375
 *    Based on code copyright (c) 1988 by Wolfgang Ocker, Puchheim,
 
376
 *                                        Ulli Dessauer, Germering and
 
377
 *                                        Reimer Mellin, Muenchen
 
378
 *                                        (W-Germany)
 
379
 *
 
380
 *    These functions can be copied and distributed freely for any
 
381
 *    non-commercial purposes.  It can only be incorporated into
 
382
 *    commercial software with the written permission of the authors.
 
383
 *
 
384
 *    TOP-specific code stripped out and adapted for less by M.Gregorie, 1996
 
385
 *
 
386
 *    address:    Wolfgang Ocker
 
387
 *                Lochhauserstrasse 35a
 
388
 *                D-8039 Puchheim
 
389
 *                West Germany
 
390
 *
 
391
 *    e-mail:     weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
 
392
 *                pyramid!tmpmbx!recco!weo
 
393
 *                pyramid!tmpmbx!nitmar!ud
 
394
 *                pyramid!tmpmbx!ramsys!ram
 
395
 *
 
396
 *                Martin Gregorie
 
397
 *                10 Sadlers Mead
 
398
 *                Harlow
 
399
 *                Essex, CM18 6HG
 
400
 *                U.K.
 
401
 *
 
402
 *                gregorie@logica.com
 
403
 */
 
404
#include <strings.h>
 
405
#include <errno.h>
 
406
extern char **environ;
 
407
extern char *getenv();
 
408
extern int  os9forkc();
 
409
static int pids[_NFILE] = { 0, 0, 0, 0, 0, 0, 0, 0,
 
410
                            0, 0, 0, 0, 0, 0, 0, 0,
 
411
                            0, 0, 0, 0, 0, 0, 0, 0,
 
412
                            0, 0, 0, 0, 0, 0, 0, 0 };
 
413
/* 
 
414
 * p o p e n
 
415
 */
 
416
FILE *popen(name, mode)
 
417
        char *name;
 
418
        char *mode;
 
419
{
 
420
    int          fd, fd2, fdsav, pid;
 
421
    static char  *argv[] = {NULL, NULL, NULL };
 
422
    static char  cmd[200];
 
423
    static char  cmd_path[200];
 
424
    char         *cp;
 
425
    char         *shell;
 
426
    FILE         *r;
 
427
    if ((shell = getenv("SHELL")) == NULL)
 
428
        return(NULL);
 
429
    cp = name;
 
430
    while (*cp == ' ')
 
431
        cp++;
 
432
    strcpy(cmd_path, cp);
 
433
    if (cp = index(cmd_path, ' '))
 
434
        *cp++ = '\0';
 
435
    strcpy(cmd, "ex ");
 
436
    strcat(cmd, cmd_path);
 
437
    if (cp)
 
438
    {
 
439
        strcat(cmd, " ");
 
440
        strcat(cmd, cp);
 
441
    }
 
442
    argv[0] = shell;
 
443
    argv[1] = cmd;
 
444
    /*
 
445
         mode is "r" (stdout) or "w" (stdin)
 
446
    */
 
447
    switch(mode[0])
 
448
    {
 
449
        case 'w':   fd = 0;
 
450
                    break;
 
451
        case 'r':   fd = 1;
 
452
                    break;
 
453
        default:    return(NULL);
 
454
    }
 
455
    if (fd == 1)
 
456
        fflush(stdout);
 
457
    fdsav = dup(fd);
 
458
    close(fd);
 
459
 
 
460
    creat("/pipe", S_IWRITE+S_IREAD);
 
461
    pid = os9exec(os9forkc, argv[0], argv, environ, 0, 0, 3);
 
462
    fd2 = dup(fd);
 
463
    close(fd);
 
464
    dup(fdsav);
 
465
    close(fdsav);
 
466
    if (pid > 0)
 
467
    {
 
468
        pids[fd2] = pid;
 
469
        r = fdopen(fd2, mode);
 
470
    }
 
471
    else
 
472
    {
 
473
        close(fd2);
 
474
        r = NULL;
 
475
    }
 
476
    return(r);
 
477
}
 
478
 
 
479
/*
 
480
 * p c l o s e
 
481
 */
 
482
int pclose(fp)
 
483
        FILE *fp;
 
484
{
 
485
    unsigned int    status;
 
486
    int             pid;
 
487
    int             fd,
 
488
                    i;
 
489
    fd = fileno(fp);
 
490
    if (pids[fd] == 0)
 
491
        return(-1);
 
492
    fflush(fp);
 
493
    fclose(fp);
 
494
    while ((pid = wait(&status)) != -1)
 
495
        if (pid == pids[fd])
 
496
            break;
 
497
        else
 
498
            for (i = 0; i < _NFILE; i++)
 
499
                if (pids[i] == pid)
 
500
                {
 
501
                    pids[i] = 0;
 
502
                    break;
 
503
                }
 
504
    if (pid == -1)
 
505
        status = -1;
 
506
    pids[fd] = 0;
 
507
    return(status);
 
508
}
 
509
#endif /* _OSK */