summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/OR_USING_C/10.5.c
blob: df6140ba58884e56eb45518409d8be5d7363b555 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <sys/wait.h>
#include <sys/signal.h>
#include <sys/ioctl.h>
#include "10.h"

waitfor()
{
    int pid;
    JOB *j;
    PROC *p;
    JOB *findjob();
    union wait status;

    /*
     * As long as we get something's status back...
     */
    while ((pid = wait3(&status, WUNTRACED, 0)) >= 0) {
        /*
         * Find the job structure which has this
         * process.
         */
        j = findjob(pid);

        /*
         * Find the process structure.
         */
        for (p = j->procs; p->pid != pid; p = p->next)
            /* empty */ ;

        /*
         * Find out what happened to the process.
         */
        if (WIFSTOPPED(status)) {
            /*
             * See if we know the reason it was
             * stopped. The w_stopsig element of
             * the structure contains the number
             * of the signal which stopped the
             * process.
             */
            switch (status.w_stopsig) {
            case SIGTTIN:
                p->status |= PTTYINPUT;
                break;
            case SIGTTOU:
                p->status |= PTTYOUTPUT;
                break;
            case SIGSTOP:
                p->status |= PSTOPSIGNAL;
                break;
            default:
                break;
            }

            p->status |= PSTOPPED;
            j->status |= JNEEDNOTE;
        }
        else if (WIFEXITED(status)) {
            /*
             * Normal termination.
             */
            if (status.w_retcode == 0)
                p->status |= PDONE;
            else
                p->status |= PEXITED;

            p->exitcode = status.w_retcode;

            /*
             * We're only going to note processes
             * exiting if all the processes in the
             * job are complete.
             */
            if (alldone(j))
                j->status |= JNEEDNOTE;
        }
        else if (WIFSIGNALED(status)) {
            p->status |= PSIGNALED;

            /*
             * Save the termination signal.
             */
            p->termsig = status.w_termsig;

            /*
             * Check for a core dump.
             */
            if (status.w_coredump)
                p->status |= PCOREDUMP;

            /*
             * We're only going to note processes
             * exiting if all the processes in the
             * job are complete.
             */
            if (alldone(j))
                j->status |= JNEEDNOTE;
        }

        /*
         * If this process is the one which was in the
         * foreground, we need to do special things,
         * and then return to the main control section
         * of the shell.
         */
        if (j->pgrp == TermPgrp) {
            /*
             * If the job is stopped, we need to call
             * the stop routine.
             */
            if (WIFSTOPPED(status)) {
                stop(j);
                printf("Stopped\n");
            }

            /*
             * If the job exited or died somehow, we
             * need to regain control of the terminal.
             */
            if (WIFEXITED(status) || WIFSIGNALED(status)) {
                ioctl(1, TIOCSPGRP, &MyPgrp);
                TermPgrp = MyPgrp;
            }

            /*
             * Go back.
             */
            return;
        }
    }
}