source: trunk/athena/etc/xdm/session_gate.c @ 3804

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