resource.c revision 1a3d60e1fc08d23194dd735c70c5984c69c4f948
1/* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $Id$ 31 */ 32 33#include "defs.h" 34 35#include <sys/resource.h> 36#ifdef LINUX 37#include <sys/times.h> 38#include <linux/kernel.h> 39#include <sys/quota.h> 40#endif /* LINUX */ 41#ifdef SUNOS4 42#include <ufs/quota.h> 43#endif /* SUNOS4 */ 44#if defined(SVR4) || defined(FREEBSD) 45#include <sys/times.h> 46#include <sys/time.h> 47#endif 48 49#if HAVE_LONG_LONG_RLIM_T 50/* 51 * Hacks for systems that have a long long rlim_t 52 */ 53 54#define rlimit64 rlimit /* Ugly hack */ 55#define rlim64_t rlim_t /* Ugly hack */ 56#define RLIM64_INFINITY RLIM_INFINITY /* You guessed it */ 57 58#define sys_getrlimit64 sys_getrlimit 59#define sys_setrlimit64 sys_setrlimit 60#endif 61 62static struct xlat resources[] = { 63#ifdef RLIMIT_CPU 64 { RLIMIT_CPU, "RLIMIT_CPU" }, 65#endif 66#ifdef RLIMIT_FSIZE 67 { RLIMIT_FSIZE, "RLIMIT_FSIZE" }, 68#endif 69#ifdef RLIMIT_DATA 70 { RLIMIT_DATA, "RLIMIT_DATA" }, 71#endif 72#ifdef RLIMIT_STACK 73 { RLIMIT_STACK, "RLIMIT_STACK" }, 74#endif 75#ifdef RLIMIT_CORE 76 { RLIMIT_CORE, "RLIMIT_CORE" }, 77#endif 78#ifdef RLIMIT_RSS 79 { RLIMIT_RSS, "RLIMIT_RSS" }, 80#endif 81#ifdef RLIMIT_NPROC 82 { RLIMIT_NPROC,"RLIMIT_NPROC" }, 83#endif 84#ifdef RLIMIT_NOFILE 85 { RLIMIT_NOFILE,"RLIMIT_NOFILE" }, 86#endif 87#ifdef RLIMIT_MEMLOCK 88 { RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK" }, 89#endif 90#ifdef RLIMIT_VMEM 91 { RLIMIT_VMEM, "RLIMIT_VMEM" }, 92#endif 93#ifdef RLIMIT_AS 94 { RLIMIT_AS, "RLIMIT_AS" }, 95#endif 96 { 0, NULL }, 97}; 98 99#if !HAVE_LONG_LONG_RLIM_T 100static char * 101sprintrlim(lim) 102long lim; 103{ 104 static char buf[32]; 105 106 if (lim == RLIM_INFINITY) 107 sprintf(buf, "RLIM_INFINITY"); 108 else if (lim > 1024 && lim%1024 == 0) 109 sprintf(buf, "%ld*1024", lim/1024); 110 else 111 sprintf(buf, "%ld", lim); 112 return buf; 113} 114 115int 116sys_getrlimit(tcp) 117struct tcb *tcp; 118{ 119 struct rlimit rlim; 120 121 if (entering(tcp)) { 122 printxval(resources, tcp->u_arg[0], "RLIMIT_???"); 123 tprintf(", "); 124 } 125 else { 126 if (syserror(tcp) || !verbose(tcp)) 127 tprintf("%#lx", tcp->u_arg[1]); 128 else if (umove(tcp, tcp->u_arg[1], &rlim) < 0) 129 tprintf("{...}"); 130 else { 131 tprintf("{rlim_cur=%s,", sprintrlim(rlim.rlim_cur)); 132 tprintf(" rlim_max=%s}", sprintrlim(rlim.rlim_max)); 133 } 134 } 135 return 0; 136} 137 138int 139sys_setrlimit(tcp) 140struct tcb *tcp; 141{ 142 struct rlimit rlim; 143 144 if (entering(tcp)) { 145 printxval(resources, tcp->u_arg[0], "RLIMIT_???"); 146 tprintf(", "); 147 if (!verbose(tcp)) 148 tprintf("%#lx", tcp->u_arg[1]); 149 else if (umove(tcp, tcp->u_arg[1], &rlim) < 0) 150 tprintf("{...}"); 151 else { 152 tprintf("{rlim_cur=%s,", sprintrlim(rlim.rlim_cur)); 153 tprintf(" rlim_max=%s}", sprintrlim(rlim.rlim_max)); 154 } 155 } 156 return 0; 157} 158#endif /* !HAVE_LONG_LONG_RLIM_T */ 159 160#if _LFS64_LARGEFILE || HAVE_LONG_LONG_RLIM_T 161static char * 162sprintrlim64(lim) 163rlim64_t lim; 164{ 165 static char buf[64]; 166 167 if (lim == RLIM64_INFINITY) 168 sprintf(buf, "RLIM64_INFINITY"); 169 else if (lim > 1024 && lim%1024 == 0) 170 sprintf(buf, "%lld*1024", (long long) lim/1024); 171 else 172 sprintf(buf, "%lld", (long long) lim); 173 return buf; 174} 175 176int 177sys_getrlimit64(tcp) 178struct tcb *tcp; 179{ 180 struct rlimit64 rlim; 181 182 if (entering(tcp)) { 183 printxval(resources, tcp->u_arg[0], "RLIMIT_???"); 184 tprintf(", "); 185 } 186 else { 187 if (syserror(tcp) || !verbose(tcp)) 188 tprintf("%#lx", tcp->u_arg[1]); 189 else if (umove(tcp, tcp->u_arg[1], &rlim) < 0) 190 tprintf("{...}"); 191 else { 192 tprintf("{rlim_cur=%s,", sprintrlim64(rlim.rlim_cur)); 193 tprintf(" rlim_max=%s}", sprintrlim64(rlim.rlim_max)); 194 } 195 } 196 return 0; 197} 198 199int 200sys_setrlimit64(tcp) 201struct tcb *tcp; 202{ 203 struct rlimit64 rlim; 204 205 if (entering(tcp)) { 206 printxval(resources, tcp->u_arg[0], "RLIMIT_???"); 207 tprintf(", "); 208 if (!verbose(tcp)) 209 tprintf("%#lx", tcp->u_arg[1]); 210 else if (umove(tcp, tcp->u_arg[1], &rlim) < 0) 211 tprintf("{...}"); 212 else { 213 tprintf("{rlim_cur=%s,", sprintrlim64(rlim.rlim_cur)); 214 tprintf(" rlim_max=%s}", sprintrlim64(rlim.rlim_max)); 215 } 216 } 217 return 0; 218} 219#endif /* _LFS64_LARGEFILES || HAVE_LONG_LONG_RLIM_T */ 220 221#ifndef SVR4 222 223static struct xlat usagewho[] = { 224 { RUSAGE_SELF, "RUSAGE_SELF" }, 225 { RUSAGE_CHILDREN, "RUSAGE_CHILDREN" }, 226#ifdef RUSAGE_BOTH 227 { RUSAGE_BOTH, "RUSAGE_BOTH" }, 228#endif 229 { 0, NULL }, 230}; 231 232#ifdef ALPHA 233void 234printrusage32(tcp, addr) 235struct tcb *tcp; 236long addr; 237{ 238 struct timeval32 239 { 240 unsigned tv_sec; 241 unsigned tv_usec; 242 }; 243 struct rusage32 244 { 245 struct timeval32 ru_utime; /* user time used */ 246 struct timeval32 ru_stime; /* system time used */ 247 long ru_maxrss; /* maximum resident set size */ 248 long ru_ixrss; /* integral shared memory size */ 249 long ru_idrss; /* integral unshared data size */ 250 long ru_isrss; /* integral unshared stack size */ 251 long ru_minflt; /* page reclaims */ 252 long ru_majflt; /* page faults */ 253 long ru_nswap; /* swaps */ 254 long ru_inblock; /* block input operations */ 255 long ru_oublock; /* block output operations */ 256 long ru_msgsnd; /* messages sent */ 257 long ru_msgrcv; /* messages received */ 258 long ru_nsignals; /* signals received */ 259 long ru_nvcsw; /* voluntary context switches */ 260 long ru_nivcsw; /* involuntary " */ 261 } ru; 262 263 if (!addr) 264 tprintf("NULL"); 265 else if (syserror(tcp) || !verbose(tcp)) 266 tprintf("%#lx", addr); 267 else if (umove(tcp, addr, &ru) < 0) 268 tprintf("{...}"); 269 else if (!abbrev(tcp)) { 270 tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ", 271 (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec, 272 (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec); 273 tprintf("ru_maxrss=%lu, ru_ixrss=%lu, ", 274 ru.ru_maxrss, ru.ru_ixrss); 275 tprintf("ru_idrss=%lu, ru_isrss=%lu, ", 276 ru.ru_idrss, ru.ru_isrss); 277 tprintf("ru_minflt=%lu, ru_majflt=%lu, ru_nswap=%lu, ", 278 ru.ru_minflt, ru.ru_majflt, ru.ru_nswap); 279 tprintf("ru_inblock=%lu, ru_oublock=%lu, ", 280 ru.ru_inblock, ru.ru_oublock); 281 tprintf("ru_msgsnd=%lu, ru_msgrcv=%lu, ", 282 ru.ru_msgsnd, ru.ru_msgrcv); 283 tprintf("ru_nsignals=%lu, ru_nvcsw=%lu, ru_nivcsw=%lu}", 284 ru.ru_nsignals, ru.ru_nvcsw, ru.ru_nivcsw); 285 } 286 else { 287 tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ...}", 288 (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec, 289 (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec); 290 } 291} 292#endif 293 294void 295printrusage(tcp, addr) 296struct tcb *tcp; 297long addr; 298{ 299 struct rusage ru; 300 301 if (!addr) 302 tprintf("NULL"); 303 else if (syserror(tcp) || !verbose(tcp)) 304 tprintf("%#lx", addr); 305 else if (umove(tcp, addr, &ru) < 0) 306 tprintf("{...}"); 307 else if (!abbrev(tcp)) { 308 tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ", 309 (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec, 310 (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec); 311 tprintf("ru_maxrss=%lu, ru_ixrss=%lu, ", 312 ru.ru_maxrss, ru.ru_ixrss); 313 tprintf("ru_idrss=%lu, ru_isrss=%lu, ", 314 ru.ru_idrss, ru.ru_isrss); 315 tprintf("ru_minflt=%lu, ru_majflt=%lu, ru_nswap=%lu, ", 316 ru.ru_minflt, ru.ru_majflt, ru.ru_nswap); 317 tprintf("ru_inblock=%lu, ru_oublock=%lu, ", 318 ru.ru_inblock, ru.ru_oublock); 319 tprintf("ru_msgsnd=%lu, ru_msgrcv=%lu, ", 320 ru.ru_msgsnd, ru.ru_msgrcv); 321 tprintf("ru_nsignals=%lu, ru_nvcsw=%lu, ru_nivcsw=%lu}", 322 ru.ru_nsignals, ru.ru_nvcsw, ru.ru_nivcsw); 323 } 324 else { 325 tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ...}", 326 (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec, 327 (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec); 328 } 329} 330 331int 332sys_getrusage(tcp) 333struct tcb *tcp; 334{ 335 if (entering(tcp)) { 336 printxval(usagewho, tcp->u_arg[0], "RUSAGE_???"); 337 tprintf(", "); 338 } 339 else 340 printrusage(tcp, tcp->u_arg[1]); 341 return 0; 342} 343 344#ifdef ALPHA 345int 346sys_osf_getrusage(tcp) 347struct tcb *tcp; 348{ 349 if (entering(tcp)) { 350 printxval(usagewho, tcp->u_arg[0], "RUSAGE_???"); 351 tprintf(", "); 352 } 353 else 354 printrusage32(tcp, tcp->u_arg[1]); 355 return 0; 356} 357#endif /* ALPHA */ 358 359#endif /* !SVR4 */ 360 361#ifdef LINUX 362 363int 364sys_sysinfo(tcp) 365struct tcb *tcp; 366{ 367 struct sysinfo si; 368 369 if (exiting(tcp)) { 370 if (syserror(tcp) || !verbose(tcp)) 371 tprintf("%#lx", tcp->u_arg[0]); 372 else if (umove(tcp, tcp->u_arg[0], &si) < 0) 373 tprintf("{...}"); 374 else { 375 tprintf("{uptime=%lu, loads=[%lu, %lu, %lu] ", 376 si.uptime, si.loads[0], si.loads[1], 377 si.loads[2]); 378 tprintf("totalram=%lu, freeram=%lu, ", 379 si.totalram, si.freeram); 380 tprintf("sharedram=%lu, bufferram=%lu} ", 381 si.sharedram, si.bufferram); 382 tprintf("totalswap=%lu, freeswap=%lu, procs=%hu}", 383 si.totalswap, si.freeswap, si.procs); 384 } 385 } 386 return 0; 387} 388 389#endif /* LINUX */ 390 391static struct xlat priorities[] = { 392 { PRIO_PROCESS, "PRIO_PROCESS" }, 393 { PRIO_PGRP, "PRIO_PGRP" }, 394 { PRIO_USER, "PRIO_USER" }, 395 { 0, NULL }, 396}; 397 398int 399sys_getpriority(tcp) 400struct tcb *tcp; 401{ 402 if (entering(tcp)) { 403 printxval(priorities, tcp->u_arg[0], "PRIO_???"); 404 tprintf(", %lu", tcp->u_arg[1]); 405 } 406 return 0; 407} 408 409int 410sys_setpriority(tcp) 411struct tcb *tcp; 412{ 413 if (entering(tcp)) { 414 printxval(priorities, tcp->u_arg[0], "PRIO_???"); 415 tprintf(", %lu, %ld", tcp->u_arg[1], tcp->u_arg[2]); 416 } 417 return 0; 418} 419 420int 421sys_nice(tcp) 422struct tcb *tcp; 423{ 424 if (entering(tcp)) 425 tprintf("%ld", tcp->u_arg[0]); 426 return 0; 427} 428 429#ifndef SUNOS4 430 431int 432sys_times(tcp) 433struct tcb *tcp; 434{ 435 struct tms tbuf; 436 437 if (exiting(tcp)) { 438 if (tcp->u_arg[0] == 0) 439 tprintf("NULL"); 440 else if (syserror(tcp)) 441 tprintf("%#lx", tcp->u_arg[0]); 442 else if (umove(tcp, tcp->u_arg[0], &tbuf) < 0) 443 tprintf("{...}"); 444 else { 445 tprintf("{tms_utime=%lu, tms_stime=%lu, ", 446 tbuf.tms_utime, tbuf.tms_stime); 447 tprintf("tms_cutime=%lu, tms_cstime=%lu}", 448 tbuf.tms_cutime, tbuf.tms_cstime); 449 } 450 } 451 return 0; 452} 453 454#endif /* !SUNOS4 */ 455 456#ifdef LINUX 457 458#define NEW_CMD(c) ((0x80<<16)+(c)) 459#define XQM_CMD(c) (('X'<<8)+(c)) 460#define NEW_COMMAND(c) (( ((c) >> SUBCMDSHIFT) & (0x80 << 16))) 461#define XQM_COMMAND(c) (( ((c) >> SUBCMDSHIFT) & ('X' << 8)) == ('X' << 8)) 462#define OLD_COMMAND(c) (!NEW_COMMAND(c) && !XQM_COMMAND(c)) 463 464static struct xlat quotacmds[] = { 465 { Q_QUOTAON, "Q_QUOTAON" }, 466 { Q_QUOTAOFF, "Q_QUOTAOFF" }, 467 { Q_GETQUOTA, "Q_GETQUOTA" }, 468 { Q_SETQUOTA, "Q_SETQUOTA" }, 469 { Q_SETUSE, "Q_SETUSE" }, 470 { Q_SYNC, "Q_SYNC" }, 471 { Q_SETQLIM, "Q_SETQLIM" }, 472 { Q_GETSTATS, "Q_GETSTATS" }, 473 { Q_RSQUASH, "Q_RSQUASH" }, 474 { NEW_CMD(0x1), "Q_SYNC" }, 475 { NEW_CMD(0x2), "Q_QUOTAON" }, 476 { NEW_CMD(0x3), "Q_QUOTAOFF" }, 477 { NEW_CMD(0x4), "Q_GETFMT" }, 478 { NEW_CMD(0x5), "Q_GETINFO" }, 479 { NEW_CMD(0x6), "Q_SETINFO" }, 480 { NEW_CMD(0x7), "Q_GETQUOTA" }, 481 { NEW_CMD(0x8), "Q_SETQUOTA" }, 482 { XQM_CMD(0x1), "Q_XQUOTAON" }, 483 { XQM_CMD(0x2), "Q_XQUOTAOFF" }, 484 { XQM_CMD(0x3), "Q_XGETQUOTA" }, 485 { XQM_CMD(0x4), "Q_XSETQLIM" }, 486 { XQM_CMD(0x5), "Q_XGETQSTAT" }, 487 { XQM_CMD(0x6), "Q_XQUOTARM" }, 488 { 0, NULL }, 489}; 490 491static struct xlat quotatypes[] = { 492 { USRQUOTA, "USRQUOTA" }, 493 { GRPQUOTA, "GRPQUOTA" }, 494 { 0, NULL }, 495}; 496 497int 498sys_quotactl(tcp) 499struct tcb *tcp; 500{ 501 if (entering(tcp)) { 502 printxval(quotacmds, (unsigned long) tcp->u_arg[0] >> SUBCMDSHIFT, "Q_???"); 503 tprintf("|"); 504 printxval(quotatypes, tcp->u_arg[0] & SUBCMDMASK, "???QUOTA"); 505 tprintf(", "); 506 printstr(tcp, tcp->u_arg[1], -1); 507 tprintf(", %lu, ", tcp->u_arg[2]); 508 } 509 else { 510 struct dqblk dq; 511 512 if (!tcp->u_arg[3]) 513 tprintf("NULL"); 514 else if (!verbose(tcp) || !OLD_COMMAND(tcp->u_arg[0])) 515 tprintf("%#lx", tcp->u_arg[3]); 516 else if (umoven(tcp, tcp->u_arg[3], sizeof(struct dqblk), 517 (char *) &dq) < 0) 518 tprintf("???"); 519 else { 520 tprintf("{"); 521 tprintf("%u, ", dq.dqb_bhardlimit); 522 tprintf("%u, ", dq.dqb_bsoftlimit); 523 tprintf("%u, ", dq.dqb_curblocks); 524 tprintf("%u, ", dq.dqb_ihardlimit); 525 tprintf("%u, ", dq.dqb_isoftlimit); 526 tprintf("%u, ", dq.dqb_curinodes); 527 tprintf("%lu, ", dq.dqb_btime); 528 tprintf("%lu", dq.dqb_itime); 529 tprintf("}"); 530 } 531 532 } 533 return 0; 534} 535 536#endif /* Linux */ 537 538#if defined(SUNOS4) || defined(FREEBSD) 539 540#ifdef FREEBSD 541#include <ufs/ufs/quota.h> 542#endif 543 544static struct xlat quotacmds[] = { 545 { Q_QUOTAON, "Q_QUOTAON" }, 546 { Q_QUOTAOFF, "Q_QUOTAOFF" }, 547 { Q_GETQUOTA, "Q_GETQUOTA" }, 548 { Q_SETQUOTA, "Q_SETQUOTA" }, 549#ifdef Q_SETQLIM 550 { Q_SETQLIM, "Q_SETQLIM" }, 551#endif 552#ifdef Q_SETUSE 553 { Q_SETUSE, "Q_SETUSE" }, 554#endif 555 { Q_SYNC, "Q_SYNC" }, 556 { 0, NULL }, 557}; 558 559int 560sys_quotactl(tcp) 561struct tcb *tcp; 562{ 563 /* fourth arg (addr) not interpreted here */ 564 if (entering(tcp)) { 565#ifdef SUNOS4 566 printxval(quotacmds, tcp->u_arg[0], "Q_???"); 567 tprintf(", "); 568 printstr(tcp, tcp->u_arg[1], -1); 569#endif 570#ifdef FREEBSD 571 printpath(tcp, tcp->u_arg[0]); 572 tprintf(", "); 573 printxval(quotacmds, tcp->u_arg[1], "Q_???"); 574#endif 575 tprintf(", %lu, %#lx", tcp->u_arg[2], tcp->u_arg[3]); 576 } 577 return 0; 578} 579 580#endif /* SUNOS4 || FREEBSD */ 581