source: trunk/athena/bin/quota/quota.c @ 13773

Revision 13773, 6.2 KB checked in by danw, 25 years ago (diff)
block SIGTSTP, SIGTTIN, SIGTTOU
Line 
1/* Copyright 1999 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16/* This is quota, which abstracts quota-checking mechanisms for
17 * various types of lockers.
18 */
19
20static const char rcsid[] = "$Id: quota.c,v 1.26 1999-10-19 20:27:46 danw Exp $";
21
22#include <ctype.h>
23#include <pwd.h>
24#include <signal.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include <locker.h>
31#include "quota.h"
32
33char **fsnames;
34locker_context context;
35
36static void usage(void);
37static void print_quota(struct quota_fs *fs);
38static void heading(uid_t uid, char *name);
39static int alldigits(char *s);
40
41int main(int argc, char **argv)
42{
43  int opt, i, status;
44  struct passwd *pw;
45  uid_t myuid;
46  int all = 0;
47  char *user;
48  uid_t uid;
49  int fsind = 0, fssize = 0, heading_printed = 0;
50  int verbose = 0;
51  struct quota_fs *fslist = NULL;
52  sigset_t mask;
53
54  myuid = getuid();
55  if (locker_init(&context, myuid, NULL, NULL) != LOCKER_SUCCESS)
56    {
57      fprintf(stderr, "quota: Could not initialize locker library.\n");
58      exit(1);
59    }
60
61  /* Block ^Z to prevent holding locks on the attachtab. */
62  sigemptyset(&mask);
63  sigaddset(&mask, SIGTSTP);
64  sigaddset(&mask, SIGTTOU);
65  sigaddset(&mask, SIGTTIN);
66  sigprocmask(SIG_BLOCK, &mask, NULL);
67
68  while ((opt = getopt(argc, argv, "af:guv")) != -1)
69    {
70      switch (opt)
71        {
72        case 'a':
73          all = 1;
74          break;
75
76        case 'v':
77          verbose = 1;
78          break;
79
80        case 'g':
81          fprintf(stderr, "quota: Group quotas no longer supported.\n");
82          exit(1);
83          break;
84
85        case 'u':
86          /* Backward-compatibility option. */
87          verbose = 1;
88          break;
89
90        case 'f':
91          if (fsind == fssize)
92            {
93              fssize = 2 * (fssize + 1);
94              fsnames = realloc(fsnames, fssize);
95              if (!fsnames)
96                {
97                  fprintf(stderr, "quota: Out of memory.\n");
98                  exit(1);
99                }
100            }
101
102          if (!strchr(optarg, '/'))
103            {
104              locker_attachent *at;
105
106              if (locker_read_attachent(context, optarg, &at) !=
107                  LOCKER_SUCCESS)
108                {
109                  fprintf(stderr, "quota: Unknown filesystem %s.\n", optarg);
110                  exit(1);
111                }
112              fsnames[fsind++] = strdup(at->mountpoint);
113              locker_free_attachent(context, at);
114            }
115          else
116            fsnames[fsind++] = optarg;
117          break;
118
119        default:
120          fprintf(stderr, "quota: %s: unknown option\n", argv[optind - 1]);
121          usage();
122          exit(1);
123        }
124    }
125
126  if (all && fsind)
127    {
128      fprintf(stderr, "quota: Can't use both -a and -f\n");
129      usage();
130      exit(1);
131    }
132
133  if (optind < argc)
134    {
135      if (optind < argc - 1)
136        {
137          fprintf(stderr, "quota: Can only specify a single user.\n");
138          exit(1);
139        }
140
141      if (alldigits(argv[optind]))
142        {
143          uid = atoi(argv[optind]);
144
145          pw = getpwuid(uid);
146          if (pw)
147            user = strdup(pw->pw_name);
148          else
149            user = "(no account)";
150        }
151      else
152        {
153          user = argv[optind];
154
155          pw = getpwnam(user);
156          if (pw)
157            uid = pw->pw_uid;
158          else
159            {
160              fprintf(stderr, "quota: No passwd entry for user %s.\n", user);
161              exit(1);
162            }
163        }
164
165      /* Check permission if not root. */
166      if (myuid != 0 && uid != myuid)
167        {
168          fprintf(stderr, "quota: %s (uid %lu): permission denied\n",
169                  user, (unsigned long) uid);
170          exit(1);
171        }
172    }
173  else
174    {
175      /* Use real uid. */
176      uid = myuid;
177      pw = getpwuid(myuid);
178      if (!pw)
179        {
180          fprintf(stderr, "quota: Could not get password entry for uid %lu.\n",
181                  (unsigned long) myuid);
182          exit(1);
183        }
184      user = strdup(pw->pw_name);
185    }
186
187  if (uid == 0)
188    {
189      if (verbose)
190        printf("no disk quota for %s (uid 0)\n", user);
191      exit(0);
192    }
193
194  fslist = get_fslist(all ? 0 : uid);
195
196  /* Now print quotas */
197  for (i = 0; fslist[i].type; i++)
198    {
199      if (!strcasecmp(fslist[i].type, "afs"))
200        status = get_afs_quota(&fslist[i], uid, verbose);
201      else if (!strcasecmp(fslist[i].type, "nfs"))
202        status = get_nfs_quota(&fslist[i], uid, verbose);
203      else
204        status = get_local_quota(&fslist[i], uid, verbose);
205
206      if (!status && fslist[i].have_quota && verbose)
207        {
208          if (!heading_printed)
209            {
210              heading(uid, user);
211              heading_printed = 1;
212            }
213          print_quota(&fslist[i]);
214        }
215    }
216  printf("\n");
217
218  for (i = 0; fslist[i].type; i++)
219    {
220      if (fslist[i].warn_blocks || fslist[i].warn_files)
221        {
222          if (!strcasecmp(fslist[i].type, "afs"))
223            print_afs_warning(&fslist[i]);
224          else
225            print_mounted_warning(&fslist[i]);
226        }
227    }
228
229  exit(0);
230}
231
232static void heading(uid_t uid, char *name)
233{
234  printf("Disk quotas for %s (uid %lu):\n", name, (unsigned long) uid);
235  printf("%-16s %8s %8s %8s    %8s %8s %8s\n",
236         "Filesystem",
237         "usage", "quota", "limit",
238         "files", "quota", "limit");
239}
240
241static void print_quota(struct quota_fs *fs)
242{
243  /* Ignore all-zero quotas */
244  if (!fs->dqb.dqb_bsoftlimit && !fs->dqb.dqb_bhardlimit
245      && !fs->dqb.dqb_curblocks && !fs->dqb.dqb_fsoftlimit
246      && !fs->dqb.dqb_fhardlimit && !fs->dqb.dqb_curfiles)
247    return;
248
249  if (strlen(fs->mount) > 16)
250    printf("%s\n%-16s ", fs->mount, "");
251  else
252    printf("%-16s ", fs->mount);
253
254  if (fs->have_blocks)
255    {
256      printf("%8u %8u %8u %2s ",
257             fs->dqb.dqb_curblocks / 2,
258             fs->dqb.dqb_bsoftlimit / 2,
259             fs->dqb.dqb_bhardlimit / 2,
260             fs->warn_blocks ? "<<" : "");
261    }
262  else
263    printf("%30s", "");
264
265  if (fs->have_files)
266    {
267      printf("%8u %8u %8u %2s ",
268             fs->dqb.dqb_curfiles,
269             fs->dqb.dqb_fsoftlimit,
270             fs->dqb.dqb_fhardlimit,
271             fs->warn_files ? "<<" : "");
272    }
273
274  printf("\n");
275}
276
277static int alldigits(char *s)
278{
279  int c;
280
281  c = *s++;
282  do {
283    if (!isdigit(c))
284      return 0;
285  } while ((c = *s++));
286  return 1;
287}
288
289static void usage(void)
290{
291  fprintf(stderr, "Usage: quota [-v] [-f filesystem...] [-u] [user]\n");
292  exit(1);
293}
Note: See TracBrowser for help on using the repository browser.