~ubuntu-branches/ubuntu/karmic/ltspfs/karmic

« back to all changes in this revision

Viewing changes to src/ltspfsd.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Balneaves
  • Date: 2006-09-18 13:01:06 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060918130106-ns6gmg2kl0oic3h6
Tags: 0.4.3-0ubuntu1
* Fixed variable check for static-devices in add_fstab_entry
* Bumped to 0.4.3
* UVF exception granted by mdz

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2005, Scott Balneaves <sbalneav@ltsp.org>
 
3
 * ltspfsd.c
 
4
 * Mainline handling for the Linux Terminal Server Project File Server Daemon.
 
5
 */
 
6
 
 
7
#include <stdio.h>
 
8
#include <stdlib.h>
 
9
#include <sys/types.h>
 
10
#include <sys/stat.h>
 
11
#include <sys/socket.h>
 
12
#include <sys/wait.h>
 
13
#include <netinet/in.h>
 
14
#include <arpa/inet.h>
 
15
#include <rpc/xdr.h>
 
16
#include <signal.h>
 
17
#include <errno.h>
 
18
#include <string.h>
 
19
#include <syslog.h>
 
20
#include <fcntl.h>
 
21
#include <unistd.h>
 
22
#include <pwd.h>
 
23
#include "ltspfs.h"
 
24
#include "ltspfsd_functions.h"
 
25
#include "common.h"
 
26
 
 
27
/*
 
28
 * Globals.
 
29
 */
 
30
 
 
31
int    debug;            /* Debug level.  0 = no debug */
 
32
int    readonly;        /* If true, make filesystem "read only" */
 
33
int    noauth;            /* If true, skip authentication */
 
34
int    syslogopen;        /* If true, then log to syslog, else stderr */
 
35
char   *mountpoint;        /* Point we're "mounted" to */
 
36
int    authenticated;    /* Mountpoint length */
 
37
int    mounted;            /* Automounter status */
 
38
 
 
39
/*
 
40
 * Signal handler function for SIGCHLD
 
41
 */
 
42
 
 
43
void
 
44
sig_chld(int signo)
 
45
{
 
46
    pid_t pid;
 
47
    int stat;
 
48
    (void) signo;
 
49
 
 
50
    pid = wait(&stat);        /* reap our child process */
 
51
    return;
 
52
}
 
53
 
 
54
 
 
55
/*
 
56
 * Signal handler function for SIGTERM
 
57
 */
 
58
 
 
59
void
 
60
sig_term(int signo)
 
61
{
 
62
    (void) signo;
 
63
    info("Recieved SIGTERM, shutting down\n");
 
64
    exit(OK);
 
65
}
 
66
 
 
67
void
 
68
timeout()
 
69
{
 
70
    exit(0);
 
71
}
 
72
 
 
73
/*
 
74
 * mainline
 
75
 */
 
76
 
 
77
int main(int argc, char *argv[])
 
78
{
 
79
 
 
80
  int sockfd, newsockfd, childpid;
 
81
  struct sockaddr_in cli_addr;
 
82
  socklen_t clilen;
 
83
  int c;
 
84
     
 
85
  authenticated = 0;
 
86
  mounted = 0;
 
87
  mountpoint = NULL;
 
88
 
 
89
  /*
 
90
   * We can begin to parse command line options.
 
91
   */
 
92
 
 
93
  debug = readonly = opterr = noauth = 0;
 
94
     
 
95
  while ((c = getopt (argc, argv, "rad")) != -1) {
 
96
    switch (c) {
 
97
      case 'r':
 
98
        readonly++;
 
99
        break;
 
100
      case 'a':
 
101
        noauth++;
 
102
        break;
 
103
      case 'd':
 
104
          debug++;
 
105
        break;
 
106
      case '?':
 
107
        fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
 
108
        return 1;
 
109
      default:
 
110
        break;
 
111
    }
 
112
  }
 
113
     
 
114
  /*
 
115
   * Some initialization work.  We call daemon(), which will chdir to /
 
116
   * so that the daemon won't lock any filesystems. The daemon() call also
 
117
   * closes STDIN, STDOUT, and STDERR, and forks.  Then, set up our umask,
 
118
   * and redirect the SIGCHLD and SIGTERM signals to handlers.  
 
119
   */
 
120
 
 
121
  if (!debug) {            /* if debug's false, then background */
 
122
    daemon(0,0);
 
123
    signal(SIGCHLD, sig_chld);
 
124
    signal(SIGTERM, sig_term);
 
125
  } else
 
126
    chdir("/");
 
127
 
 
128
    umask(0);
 
129
 
 
130
  /*
 
131
   * open our logging.
 
132
   */
 
133
 
 
134
  if (!debug) {
 
135
    openlog(argv[0], LOG_PID, LOG_USER);
 
136
    syslogopen++;
 
137
  }
 
138
 
 
139
  /*
 
140
   * Open our socket
 
141
   */
 
142
 
 
143
  sockfd = bindsocket(SERVER_PORT);
 
144
 
 
145
  /*
 
146
   * Log informational message to indicate program starting
 
147
   */
 
148
 
 
149
  info("Program started\n");
 
150
  
 
151
  /*
 
152
   * Calculate the length of the cli_addr structure (needed for the accept)
 
153
   */
 
154
 
 
155
  clilen = sizeof(cli_addr);
 
156
 
 
157
  for (;;) {
 
158
 
 
159
    /*
 
160
     * Accept incoming connection
 
161
     */
 
162
 
 
163
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
 
164
    if (newsockfd < 0)
 
165
      error_die("Can't accept connection");
 
166
 
 
167
    if (!debug)            /* In debug mode, don't fork */
 
168
      childpid = fork();
 
169
    else
 
170
      childpid = 0;
 
171
 
 
172
    if (childpid < 0)
 
173
      error_die("fork error");    /* If fork fails, something's wrong */
 
174
    else if (childpid == 0) {
 
175
      close(sockfd);        /* Child process, pass work off */
 
176
      handle_connection(newsockfd);
 
177
      exit(OK);            /* exit child, SIGCHLD sent */
 
178
    }
 
179
    close(newsockfd);        /* parent */
 
180
  }
 
181
  return OK;            /* return 0 from main */
 
182
}
 
183
 
 
184
/*
 
185
 * handle_connection is where the "work" gets done.  Anything you want to "do"
 
186
 * as a network daemon should be done here.
 
187
 *
 
188
 * Dispatch ltspfs calls to ltspfs_dispatch.
 
189
 */
 
190
 
 
191
void handle_connection(int sockfd)
 
192
{
 
193
  XDR in;
 
194
  int n;
 
195
  int i, q;
 
196
  char line[LTSP_MAXBUF];
 
197
  char *lineptr;
 
198
  fd_set set;                    /* For select */
 
199
  struct timeval automount_timeout;             /* Timeout */
 
200
  int nleft, nread;
 
201
  int r;
 
202
 
 
203
 
 
204
  for (;;) {
 
205
    FD_ZERO(&set);
 
206
    FD_SET(sockfd, &set);
 
207
    xdrmem_create(&in, line, LTSP_MAXBUF, XDR_DECODE);
 
208
    lineptr = line;
 
209
 
 
210
    /*
 
211
     * Sigh.  I really hate to have to re-duplicate most of the readn 
 
212
     * functionality here, but it's simply cleaner to not butcher the _readn
 
213
     * and _writen primitives just to handle automount timeouts. Soooo....
 
214
     */
 
215
 
 
216
    automount_timeout.tv_sec  = AUTOMOUNT_TIMEOUT;
 
217
    automount_timeout.tv_usec = 0;
 
218
    r = select(FD_SETSIZE, &set, NULL, NULL, &automount_timeout);
 
219
    if (r < 0)
 
220
      error_die("handle_connection: select error\n");
 
221
    else if (r == 0) {
 
222
      if (mounted)
 
223
        am_umount(mountpoint);        /* this will return */
 
224
      continue;            /* Back to the top of the for(;;) loop */
 
225
    }
 
226
 
 
227
    nleft = BYTES_PER_XDR_UNIT;
 
228
 
 
229
    while (nleft > 0) {
 
230
      nread = read(sockfd, lineptr, nleft);
 
231
      if (nread < 0)
 
232
        error_die("handle_connection: readline error\n");
 
233
      else if (nread == 0)
 
234
    return;            /* EOF, connection closed */
 
235
 
 
236
      nleft   -= nread;
 
237
      lineptr += nread;
 
238
    }
 
239
    
 
240
    xdr_int(&in, &i);
 
241
    if (debug)
 
242
      info("Packet length: %d\n", i);
 
243
    n = readn(sockfd, lineptr, (i - BYTES_PER_XDR_UNIT));
 
244
    if (n == 0)
 
245
      return;            /* connection closed */
 
246
    else if (n < 0)
 
247
      error_die("handle_connection: readline error\n");
 
248
 
 
249
    /*
 
250
     *  OK We've got our command line, pass this off to ltspfs_dispatch
 
251
     */
 
252
 
 
253
    if (debug) {
 
254
      info("Packet buffer: ");
 
255
      for (q = 0; q < i; q++)
 
256
        info("%x", line[q]);
 
257
      info("\n");
 
258
    }
 
259
 
 
260
    ltspfs_dispatch(sockfd, &in);
 
261
    
 
262
    /*
 
263
     * Well, we're back.  Reset our position to the beginning.
 
264
     */
 
265
    xdr_destroy(&in);
 
266
  }
 
267
}
 
268