1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1992-2012 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
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) 2011-08-27 $\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 = getpgrp();
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 #if _lib_getsid
80 *pn = getsid(0);
81 #else
82 *pn = -1;
83 #endif
84 else if (streq(s, "format"))
85 *ps = (char*)handle;
86 else
87 {
88 error(2, "%s: unknown format identifier", s);
89 return 0;
90 }
91 return 1;
92 }
93
94 int
b_pids(int argc,char ** argv,Shbltin_t * context)95 b_pids(int argc, char** argv, Shbltin_t* context)
96 {
97 char* format = 0;
98
99 cmdinit(argc, argv, context, ERROR_CATALOG, 0);
100 for (;;)
101 {
102 switch (optget(argv, usage))
103 {
104 case 'f':
105 format = opt_info.arg;
106 continue;
107 case '?':
108 error(ERROR_USAGE|4, "%s", opt_info.arg);
109 break;
110 case ':':
111 error(2, "%s", opt_info.arg);
112 break;
113 }
114 break;
115 }
116 argv += opt_info.index;
117 if (error_info.errors || *argv)
118 error(ERROR_USAGE|4, "%s", optusage(NiL));
119 if (!format)
120 format = FORMAT;
121 sfkeyprintf(sfstdout, format, format, key, NiL);
122 sfprintf(sfstdout, "\n");
123 return 0;
124 }
125