ecuLCK.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. #ifdef SVR4
  2. #define USE_SVR4_MKDEV_H /* jeff@samantha.chi.il.us SVR4 lock file */
  3. #endif
  4. /*+-----------------------------------------------------------------------
  5. ecuLCK.c -- ECU lock file management (testing)
  6. wht@wht.net
  7. Defined functions:
  8. LINST_text(linst)
  9. is_active_lock(name)
  10. line_lock_status(ttyname)
  11. lopen_error_reset()
  12. make_lock_name(ttyname, lock_file_name)
  13. This module provides the functions for testing lock files.
  14. It is included by ECU and other utilities (such as ecuungetty).
  15. A companion module, eculock.c, has functions for creating lock files.
  16. ------------------------------------------------------------------------*/
  17. /*+:EDITS:*/
  18. /*:04-26-2000-11:15-wht@bob-RELEASE 4.42 */
  19. /*:01-24-1997-02:37-wht@yuriatin-SOURCE RELEASE 4.00 */
  20. /*:09-11-1996-20:00-wht@yuriatin-3.48-major telnet,curses,structural overhaul */
  21. /*:09-09-1996-03:39-wht@yuriatin-add LINST_TELNETFAIL */
  22. /*:08-11-1996-02:10-wht@kepler-rename ecu_log_event to logevent */
  23. /*:12-06-1995-11:41-wht@n4hgf-revert ODT3 lock files to previous */
  24. /*:12-03-1995-19:57-wht@gyro-use Setuid */
  25. /*:11-23-1995-11:20-wht@kepler-source control 3.37 for tsx-11 */
  26. /*:11-14-1995-10:23-wht@kepler-3.37.80-source control point: SOCKETS */
  27. /*:09-04-1995-18:57-wht@n4hgf-fix broken 32v5 lock file change */
  28. /*:09-01-1995-17:36-wht@n4hgf-32v5 cvts ALL ttynm chars to lc for lock file */
  29. /*:06-12-1995-15:03-wht@n4hgf-if ecu has uucp euid, make use of it */
  30. /*:05-04-1994-04:38-wht@n4hgf-ECU release 3.30 */
  31. /*:01-25-1994-17:36-wht@n4hgf-rename USE_DECIMAL_PIDS->CFG_BinaryUucpPids */
  32. /*:12-18-1993-18:12-wht@n4hgf-use CFG_BinaryUucpPids in place of HONEYDANBER */
  33. /*:11-14-1993-12:33-wht@n4hgf-HP-UX port by Carl Wuebker at HP */
  34. /*:08-18-1993-05:51-wht@n4hgf-cvting to enum linst uncovered gcc bug */
  35. /*:06-12-1993-12:18-wht@n4hgf-put LINST_text here for ecuungetty debug reach */
  36. /*:06-11-1993-17:14-wht@n4hgf-beef up ISLOCK logevent */
  37. /*:10-07-1992-21:09-jeff@samantha.chi.il.us-SVR4 lock file correction */
  38. /*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  39. /*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  40. /*:08-21-1992-13:39-wht@n4hgf-rewire direct/modem device use */
  41. /*:04-24-1992-21:59-wht@n4hgf-more SCO tty name normalizing */
  42. /*:08-25-1991-14:39-wht@n4hgf-ISCSVR4 port thanks to aega84!lh */
  43. /*:08-21-1991-03:37-wht@n4hgf-kill LINST_INVALID check */
  44. /*:08-11-1991-18:06-wht@n4hgf-SCO_TTY_NAMING considerations */
  45. /*:08-09-1991-11:07-wht@n4hgf-configurable lock directory */
  46. /*:08-07-1991-14:41-wht@n4hgf-race with ecuungetty over lock resolved */
  47. /*:07-25-1991-12:55-wht@n4hgf-ECU release 3.10 */
  48. /*:11-19-1990-01:05-wht@n4hgf-remove lock in is_active_lock if we locked */
  49. /*:10-16-1990-20:43-wht@n4hgf-add SHARE_DEBUG */
  50. /*:09-19-1990-19:36-wht@n4hgf-logevent now gets pid for log from caller */
  51. /*:08-14-1990-20:39-wht@n4hgf-ecu3.00-flush old edit history */
  52. #include "ecu.h"
  53. #include "utmpstatus.h"
  54. #if defined(SVR4)
  55. #ifdef USE_SVR4_MKDEV_H
  56. #include <sys/mkdev.h>
  57. #else
  58. #include <sys/sysmacros.h>
  59. #endif /* USE_SVR4_MKDEV_H */
  60. #endif
  61. extern int errno;
  62. extern char ungetty_ttyname[];
  63. char *lock_dir_name = CFG_LockDir; /* location of LCK.. files */
  64. int setuid_uucp; /* true if ecu is owned by uucp and chmod +s */
  65. short uid;
  66. short euid;
  67. short uid_uucp;
  68. /*+-------------------------------------------------------------------------
  69. lopen_error_reset() - clear lopen_err_str
  70. --------------------------------------------------------------------------*/
  71. void
  72. lopen_error_reset()
  73. {
  74. lopen_err_str[0] = 0;
  75. } /* end of lopen_error_reset */
  76. /*+-------------------------------------------------------------------------
  77. LINST_text(linst) - enum linst to text
  78. --------------------------------------------------------------------------*/
  79. char *
  80. LINST_text(linst)
  81. enum linst linst;
  82. {
  83. static char linst_s80[80];
  84. extern uchar last_ugstat;
  85. char *UG_text();
  86. if (lopen_err_str[0])
  87. return (lopen_err_str);
  88. /*
  89. * The first bug I have found in gcc 2.3.3 (and 2.4.5 is out):
  90. * Reading specs from /usr/local/lib/gcc-lib/i486-sco3.2v4/2.3.3/specs
  91. * gcc version 2.3.3
  92. *
  93. * if the (int) cast is removed from the following, a large positive
  94. * integer (a pid) in linst results in "OK" being returned. Go figure.
  95. */
  96. switch ((int)linst)
  97. {
  98. case LINST_OK:
  99. return ("OK");
  100. case LINST_INVALID:
  101. return ("invalid line name");
  102. case LINST_UNKPID:
  103. return ("unknown pid is using line");
  104. case LINST_LCKERR:
  105. return ("error creating lock file");
  106. case LINST_NODEV:
  107. return ("line does not exist");
  108. case LINST_ALREADY:
  109. return ("line already open!?");
  110. case LINST_OPNFAIL:
  111. sprintf(linst_s80, "open error (%-.60s)", strerror(errno));
  112. return (linst_s80);
  113. case LINST_ENABLED:
  114. return ("line enabled for incoming login");
  115. case LINST_ENABLED_IN_USE:
  116. return ("line used by incoming login");
  117. case LINST_DIALOUT_IN_USE:
  118. return ("line used by another dial out");
  119. case LINST_NOPTY:
  120. return ("ptys not supported");
  121. case LINST_WEGOTIT:
  122. return ("line already locked by this process");
  123. case LINST_ECUUNGETTY:
  124. sprintf(linst_s80, "ecuungetty error (%-.45s)",
  125. UG_text(last_ugstat));
  126. return (linst_s80);
  127. case LINST_ECUUNGETTY2:
  128. return ("ecuungetty execution error");
  129. case LINST_NOTCHR:
  130. return ("not a character special device");
  131. #ifdef CFG_TelnetOption
  132. case LINST_TELNETFAIL:
  133. return ("telnet open failed");
  134. #endif
  135. }
  136. if (linst > 0)
  137. sprintf(linst_s80, "pid %d using line", linst);
  138. else
  139. sprintf(linst_s80, "unknown line error %d", linst);
  140. return (linst_s80);
  141. } /* end of LINST_text */
  142. /*+-------------------------------------------------------------------------
  143. make_lock_name(ttyname,lock_file_name)
  144. --------------------------------------------------------------------------*/
  145. enum linst
  146. make_lock_name(ttyname, lock_file_name)
  147. char *ttyname;
  148. char *lock_file_name;
  149. {
  150. #if defined(SVR4)
  151. struct stat tbuf;
  152. if (stat(ttyname, &tbuf) < 0)
  153. {
  154. if (errno == ENOENT)
  155. return (LINST_NODEV); /* device does not exist */
  156. else
  157. return (LINST_OPNFAIL); /* could not access line */
  158. }
  159. sprintf(lock_file_name, "%s/LK.%03u.%03u.%03u",
  160. lock_dir_name, major(tbuf.st_dev),
  161. #ifndef USE_SVR4_MKDEV_H
  162. tbuf.st_rdev >> 18,
  163. #else
  164. major(tbuf.st_rdev),
  165. #endif /* USE_SVR4_MKDEV_H */
  166. minor(tbuf.st_rdev));
  167. #else
  168. /*
  169. * SVR3 and SCO
  170. */
  171. strcpy(lock_file_name, lock_dir_name);
  172. strcat(lock_file_name, "/LCK..");
  173. #if defined(SCO32v5)
  174. /*
  175. * starting with 32v5 and as early as ODT 3.0, ALL characters of the
  176. * tty name are converted to lower case; this takes care of tty names
  177. * like tty1A00
  178. */
  179. lock_file_name += strlen(lock_file_name);
  180. strcpy(lock_file_name, ttyname + 5);
  181. while (*lock_file_name)
  182. {
  183. *lock_file_name = to_lower(*lock_file_name);
  184. lock_file_name++;
  185. }
  186. #else
  187. #ifdef SCO_TTY_NAMING
  188. /*
  189. * the last character of the tty name is converted to lower case; that
  190. * is, the direct ttyname is used for lock files
  191. */
  192. strcat(lock_file_name, direct_tty(ttyname) + 5);
  193. #else
  194. strcat(lock_file_name, ttyname + 5);
  195. #endif /* SCO_TTY_NAMING */
  196. #endif /* SCO32v5 */
  197. #endif /* SVR4 */
  198. return (LINST_OK);
  199. } /* end of make_lock_name */
  200. /*+-------------------------------------------------------------------------
  201. is_active_lock(name) - check to see if lock still active
  202. if not unlink any old lock name
  203. --------------------------------------------------------------------------*/
  204. enum linst
  205. is_active_lock(name)
  206. char *name;
  207. {
  208. int itmp;
  209. CFG_PidType lockpid = 0;
  210. int fd;
  211. enum linst linst = LINST_OK;
  212. char pidstr[16];
  213. errno = 0;
  214. if ((fd = open(name, O_RDONLY, 0)) < 0)
  215. {
  216. if (errno != ENOENT)
  217. linst = LINST_LCKERR;
  218. goto RETURN_STATUS;
  219. }
  220. errno = 0;
  221. #if defined(CFG_BinaryUucpPids)
  222. itmp = read(fd, (char *)&lockpid, sizeof(int));
  223. close(fd);
  224. if (itmp != sizeof(int))
  225. goto UNLINK_OLD_LOCK;
  226. #else
  227. itmp = read(fd, (char *)pidstr, 11);
  228. pidstr[11] = 0;
  229. close(fd);
  230. if (itmp != 11)
  231. goto UNLINK_OLD_LOCK;
  232. lockpid = atoi(pidstr);
  233. #endif
  234. /* if we are the locker, return no error */
  235. errno = 0;
  236. if (lockpid == xmtr_pid)
  237. {
  238. linst = LINST_WEGOTIT;
  239. goto RETURN_STATUS;
  240. }
  241. if ((!(itmp = kill(lockpid, 0))) || (errno != ESRCH))
  242. {
  243. errno = EACCES; /* for termecu() */
  244. linst = (enum linst)lockpid;
  245. goto RETURN_STATUS;
  246. }
  247. UNLINK_OLD_LOCK:
  248. errno = 0;
  249. if (setuid_uucp)
  250. Setuid(uid_uucp);
  251. if (unlink(name))
  252. linst = LINST_LCKERR;
  253. if (setuid_uucp)
  254. Setuid(uid);
  255. RETURN_STATUS:
  256. #if defined(LOCK_DEBUG)
  257. {
  258. char s512[512];
  259. char *cp;
  260. cp = strrchr(name, '/');
  261. if (cp)
  262. cp++;
  263. else
  264. cp = name;
  265. sprintf(s512, "LOCKED? %s: %s", cp,
  266. (linst != LINST_OK) ? LINST_text(linst) : "NO");
  267. if (linst)
  268. sprintf(s512 + strlen(s512), " (%s)", strerror(errno));
  269. logevent(getpid(), s512);
  270. }
  271. #endif
  272. return (linst);
  273. } /* end of is_active_lock */
  274. /*+-----------------------------------------------------------------------
  275. line_lock_status(ttyname)
  276. ttyname must be of style "/dev/ttyxx"
  277. Returns locking pid if locked else LOPEN lock error code (< 0) else 0
  278. ------------------------------------------------------------------------*/
  279. enum linst
  280. line_lock_status(ttyname)
  281. char *ttyname;
  282. {
  283. enum linst linst = LINST_OK;
  284. char lock_file_name[128];
  285. if (linst = make_lock_name(ttyname, lock_file_name))
  286. return (linst);
  287. if (linst = is_active_lock(lock_file_name))
  288. return (linst);
  289. return (LINST_OK);
  290. } /* end of line_lock_status */
  291. /* end of ecuLCK.c */
  292. /* vi: set tabstop=4 shiftwidth=4: */