source: trunk/athena/bin/session/session_gate.c @ 6647

Revision 6647, 4.7 KB checked in by miki, 31 years ago (diff)
ported to Solaris2.1
Line 
1/*
2 *  session_gate - Keeps session alive by continuing to run
3 *
4 *      $Source: /afs/dev.mit.edu/source/repository/athena/bin/session/session_gate.c,v $
5 *      $Header: /afs/dev.mit.edu/source/repository/athena/bin/session/session_gate.c,v 1.9 1993-05-20 12:52:48 miki Exp $
6 *      $Author: miki $
7 */
8
9#include <signal.h>
10#ifndef SOLARIS
11#include <strings.h>
12#else
13#include <strings.h>
14#include <sys/fcntl.h>
15#endif
16#include <sys/types.h>
17#include <sys/file.h>
18#include <sys/stat.h>
19#include <sys/wait.h>
20
21#define BUFSIZ 1024
22#define MINUTE 60
23#define PID_FILE_TEMPLATE "/tmp/session_gate_pid."
24
25static char filename[80];
26
27void main( );
28int itoa( );
29void cleanup( );
30void logout( );
31void clean_child( );
32time_t check_pid_file( );
33time_t create_pid_file( );
34time_t update_pid_file( );
35void write_pid_to_file( );
36
37
38void main(argc, argv)
39int argc;
40char **argv;
41{
42    int pid;
43    int parentpid;
44    char buf[10];
45    time_t mtime;
46    int dologout = 0;
47
48    if (argc == 2 && !strcmp(argv[1], "-logout"))
49      dologout = 1;
50
51    pid = getpid();
52    parentpid = getppid();
53   
54    /*  Set up signal handlers for a clean exit  */
55
56    if (dologout) {
57        signal(SIGHUP, logout);
58        signal(SIGINT, logout);
59        signal(SIGQUIT, logout);
60        signal(SIGTERM, logout);
61    } else {
62        signal(SIGHUP, cleanup);
63        signal(SIGINT, cleanup);
64        signal(SIGQUIT, cleanup);
65        signal(SIGTERM, cleanup);
66    }
67    signal(SIGCHLD, clean_child);       /* Clean up zobmied children */
68
69    /*  Figure out the filename  */
70
71    strcpy(filename, PID_FILE_TEMPLATE);
72    itoa(getuid(), buf);
73    strcat(filename, buf);
74
75    /*  Put pid in file for the first time  */
76
77    mtime = check_pid_file(filename, pid, (time_t)0);
78
79    /*
80     * Now sit and wait.  If a signal occurs, catch it, cleanup, and exit.
81     * Every minute, wake up and perform the following checks:
82     *   - If parent process does not exist, cleanup and exit.
83     *   - If pid file has been modified or is missing, refresh it.
84     */
85   
86    while (1)
87      {
88          sleep(MINUTE);
89          clean_child();        /* In case there are any zombied children */
90          if (parentpid != getppid())
91            cleanup();
92          mtime = check_pid_file(filename, pid, mtime);
93      }
94}
95
96static powers[] = {100000,10000,1000,100,10,1,0};
97
98int itoa(x, buf)
99int x;
100char *buf;
101{
102    int i;
103    int pos=0;
104    int digit;
105
106    for (i = 0; powers[i]; i++)
107      {
108          digit = (x/powers[i]) % 10;
109          if ((pos > 0) || (digit != 0) || (powers[i+1] == 0))
110            buf[pos++] = '0' + (char) digit;
111      }
112    buf[pos] = '\0';
113    return pos;
114}
115
116
117void cleanup( )
118{
119    unlink(filename);
120    exit(0);
121}
122
123void logout( )
124{
125    int f;
126
127    /* Ignore Alarm in child since HUP probably arrived during
128     * sleep() in main loop.
129     */
130    signal(SIGALRM, SIG_IGN);
131    unlink(filename);
132    f = open(".logout", O_RDONLY, 0);
133    if (f >= 0) {
134        dup2(f, 0);
135        execl("/bin/athena/tcsh", "logout", 0);
136    }
137    exit(0);
138}
139
140/*
141 * clean_child() --
142 *      Clean up any zombied children that are awaiting this process's
143 *      acknowledgement of the child's death.
144 */
145void clean_child( )
146{
147    wait3(0, WNOHANG, 0);
148}
149
150time_t check_pid_file(filename, pid, mtime)
151char* filename;
152int pid;
153time_t mtime;
154{
155    struct stat st_buf;
156
157    if (stat(filename, &st_buf) == -1)
158      return create_pid_file(filename, pid);    /*  File gone:  create  */
159    else if (st_buf.st_mtime > mtime)
160      return update_pid_file(filename, pid);    /*  File changed:  update  */
161    else
162      return mtime;                             /*  File unchanged  */
163}
164
165
166time_t create_pid_file(filename, pid)
167char* filename;
168int pid;
169{
170    int fd;
171    struct stat st_buf;
172
173    if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0)) >= 0)
174      {
175          write_pid_to_file(pid, fd);
176          fchmod(fd, S_IREAD | S_IWRITE);   /* set file mode 600 */
177          close(fd);
178      }
179
180    stat(filename, &st_buf);
181    return st_buf.st_mtime;
182}
183
184
185time_t update_pid_file(filename, pid)
186char* filename;
187int pid;
188{
189    int fd;
190    char buf[BUFSIZ];
191    int count;
192    char* start;
193    char* end;
194    struct stat st_buf;
195
196    /*  Determine if the file already contains the pid  */
197
198    if ((fd = open(filename, O_RDONLY, 0)) >= 0)
199      {
200          if ((count = read(fd, buf, BUFSIZ-1)) > 0)
201            {
202                buf[count-1] = '\0';
203                start = buf;
204                while ((end = index(start, '\n')) != 0)
205                  {
206                      *end = '\0';
207                      if (atoi(start) == pid)
208                        {
209                            stat(filename, &st_buf);
210                            return st_buf.st_mtime;
211                        }
212                      start = end + 1;
213                  }
214            }
215          close(fd);
216      }
217
218    /*  Append the pid to the file  */
219
220    if ((fd = open(filename, O_WRONLY | O_APPEND, 0)) >= 0)
221      {
222          write_pid_to_file(pid, fd);
223          close(fd);
224      }
225         
226    stat(filename, &st_buf);
227    return st_buf.st_mtime;
228}
229
230
231void write_pid_to_file(pid, fd)
232int pid;
233int fd;
234{
235    char buf[10];
236
237    itoa(pid, buf);
238    strcat(buf, "\n");
239    write(fd, buf, strlen(buf));
240}
Note: See TracBrowser for help on using the repository browser.