1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1992-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * *
20 ***********************************************************************/
21 #pragma prototyped
22
23 #define FORMAT "PID=%(pid)d PPID=%(ppid)d PGID=%(pgid)d TID=%(tid)d SID=%(sid)d"
24
25 static const char usage[] =
26 "[-?\n@(#)$Id: pids (AT&T Research) 2008-04-01 $\n]"
27 USAGE_LICENSE
28 "[+NAME?pids - list calling shell process ids]"
29 "[+DESCRIPTION?When invoked as a shell builtin, \bpids\b lists one or "
30 "more of the calling process ids determined by \bgetpid\b(2), "
31 "\bgetppid\b(2), \bgetpgrp\b(2), \btcgetpgrp\b(2) and \bgetsid\b(2). "
32 "Unknown or invalid ids have the value \b-1\b.]"
33 "[f:format?List the ids specified by \aformat\a. \aformat\a follows "
34 "\bprintf\b(3) conventions, except that \bsfio\b(3) inline ids are used "
35 "instead of arguments: "
36 "%[-+]][\awidth\a[.\aprecis\a[.\abase\a]]]]]](\aid\a)\achar\a. The "
37 "supported \aid\as are:]:[format:=" FORMAT "]"
38 "{"
39 "[+pid?The process id.]"
40 "[+pgid?The process group id.]"
41 "[+ppid?The parent process id.]"
42 "[+tid|tty?The controlling terminal id.]"
43 "[+sid?The session id.]"
44 "}"
45 "[+SEE ALSO?\bgetpid\b(2), \bgetppid\b(2), \bgetpgrp\b(2), "
46 "\btcgetpgrp\b(2), \bgetsid\b(2)]"
47 ;
48
49 #include <cmd.h>
50 #include <ast_tty.h>
51 #include <sfdisc.h>
52
53 /*
54 * sfkeyprintf() lookup
55 * handle==0 for heading
56 */
57
58 static int
key(void * handle,Sffmt_t * fp,const char * arg,char ** ps,Sflong_t * pn)59 key(void* handle, Sffmt_t* fp, const char* arg, char** ps, Sflong_t* pn)
60 {
61 register char* s;
62 int fd;
63 long tid;
64
65 if (!(s = fp->t_str) || streq(s, "pid"))
66 *pn = getpid();
67 else if (streq(s, "pgid"))
68 *pn = getpgid(0);
69 else if (streq(s, "ppid"))
70 *pn = getppid();
71 else if (streq(s, "tid") || streq(s, "tty"))
72 {
73 for (fd = 0; fd < 3; fd++)
74 if ((tid = tcgetpgrp(fd)) >= 0)
75 break;
76 *pn = tid;
77 }
78 else if (streq(s, "sid"))
79 *pn = getsid(0);
80 else if (streq(s, "format"))
81 *ps = (char*)handle;
82 else
83 {
84 error(2, "%s: unknown format identifier", s);
85 return 0;
86 }
87 return 1;
88 }
89
90 int
b_pids(int argc,char ** argv,void * context)91 b_pids(int argc, char** argv, void* context)
92 {
93 char* format = 0;
94
95 cmdinit(argc, argv, context, ERROR_CATALOG, 0);
96 for (;;)
97 {
98 switch (optget(argv, usage))
99 {
100 case 'f':
101 format = opt_info.arg;
102 continue;
103 case '?':
104 error(ERROR_USAGE|4, "%s", opt_info.arg);
105 continue;
106 case ':':
107 error(2, "%s", opt_info.arg);
108 continue;
109 }
110 break;
111 }
112 argv += opt_info.index;
113 if (error_info.errors || *argv)
114 error(ERROR_USAGE|4, "%s", optusage(NiL));
115 if (!format)
116 format = FORMAT;
117 sfkeyprintf(sfstdout, format, format, key, NiL);
118 sfprintf(sfstdout, "\n");
119 return 0;
120 }
121